Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8ae0a42

Browse files
committed
Added day 2018-15
1 parented10edc commit8ae0a42

File tree

1 file changed

+322
-0
lines changed

1 file changed

+322
-0
lines changed

‎2018/15-Beverage Bandits.py‎

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
# -------------------------------- Input data -------------------------------- #
2+
importos,pathfinding,complex_utils,copy
3+
4+
test_data= {}
5+
6+
test=1
7+
test_data[test]= {
8+
"input":"""#######
9+
#G..#E#
10+
#E#E.E#
11+
#G.##.#
12+
#...#E#
13+
#...E.#
14+
#######""",
15+
"expected": ["36334 (37, 982, E)","Unknown"],
16+
}
17+
18+
test+=1
19+
test_data[test]= {
20+
"input":"""#######
21+
#E..EG#
22+
#.#G.E#
23+
#E.##E#
24+
#G..#.#
25+
#..E#.#
26+
#######""",
27+
"expected": ["39514 (46 rounds, 859 HP, E)","Unknown"],
28+
}
29+
30+
test+=1
31+
test_data[test]= {
32+
"input":"""#######
33+
#E.G#.#
34+
#.#G..#
35+
#G.#.G#
36+
#G..#.#
37+
#...E.#
38+
#######""",
39+
"expected": ["27755 (35 rounds, 793 HP, G)","Unknown"],
40+
}
41+
42+
test+=1
43+
test_data[test]= {
44+
"input":"""#######
45+
#.G...#
46+
#...EG#
47+
#.#.#G#
48+
#..G#E#
49+
#.....#
50+
#######""",
51+
"expected": ["Unknown","15 attack power, 4988 (29 rounds, 172 HP)"],
52+
}
53+
54+
test="real"
55+
input_file=os.path.join(
56+
os.path.dirname(__file__),
57+
"Inputs",
58+
os.path.basename(__file__).replace(".py",".txt"),
59+
)
60+
test_data[test]= {
61+
"input":open(input_file,"r+").read().strip(),
62+
"expected": ["207542","64688"],
63+
}
64+
65+
# -------------------------------- Control program execution ------------------------- #
66+
67+
case_to_test=4
68+
part_to_test=2
69+
verbose_level=2
70+
71+
# -------------------------------- Initialize some variables ------------------------- #
72+
73+
puzzle_input=test_data[case_to_test]["input"]
74+
puzzle_expected_result=test_data[case_to_test]["expected"][part_to_test-1]
75+
puzzle_actual_result="Unknown"
76+
77+
78+
# -------------------------------- Player class definition --------------------------- #
79+
80+
81+
classPlayer:
82+
position=0
83+
type=""
84+
HP=200
85+
graph=""
86+
alive=True
87+
attack_power=3
88+
89+
def__init__(self,type,position,attack_power=3):
90+
self.position=position
91+
self.type=type
92+
ifself.type=="E":
93+
self.attack_power=attack_power
94+
95+
def__lt__(self,other):
96+
ifself.position.imag<other.position.imag:
97+
returnTrue
98+
else:
99+
returnself.position.real<other.position.real
100+
101+
defmove(self,graph,creatures):
102+
"""
103+
Searches for the closest ennemy
104+
105+
:param Graph graph: The game map
106+
:param list creatures: A list of creatures
107+
:return: The target position
108+
"""
109+
110+
# Modify graph so that allies are walls, ennemies are traps
111+
self.graph=copy.deepcopy(graph)
112+
verbose=False
113+
ifFalse:
114+
verbose=True
115+
allies= [
116+
c.position
117+
forcincreatures
118+
ifc.type==self.typeandc!=selfandc.alive
119+
]
120+
ennemies= [c.positionforcincreaturesifc.type!=self.typeandc.alive]
121+
self.graph.add_traps(ennemies)
122+
self.graph.add_walls(allies)
123+
124+
# Run BFS from my position to determine closest target
125+
self.graph.breadth_first_search(self.position)
126+
127+
# Determine all target positions (= cells next to the ennemies), then choose closest
128+
target_positions= [
129+
(self.graph.distance_from_start[e+dir],e+dir)
130+
foreinennemies
131+
fordirincomplex_utils.directions_straight
132+
ife+dirinself.graph.distance_from_start
133+
]
134+
ifnottarget_positions:
135+
return
136+
137+
min_distance=min([pos[0]forposintarget_positions])
138+
closest_targets= [pos[1]forposintarget_positionsifpos[0]==min_distance]
139+
target=complex_utils.complex_sort(closest_targets,"reading")[0]
140+
141+
ifmin_distance==0:
142+
return
143+
144+
ifverbose:
145+
print("before",self.position,target_positions,closest_targets,target)
146+
147+
# Then we do the opposite, to know in which direction to go
148+
# Run BFS from the target
149+
self.graph.breadth_first_search(target)
150+
# Determine which direction to go to is best
151+
next_positions= [
152+
(self.graph.distance_from_start[self.position+dir],self.position+dir,)
153+
fordirincomplex_utils.directions_straight
154+
ifself.position+dirinself.graph.vertices
155+
]
156+
min_distance=min([pos[0]forposinnext_positions])
157+
closest_positions= [pos[1]forposinnext_positionsifpos[0]==min_distance]
158+
target=complex_utils.complex_sort(closest_positions,"reading")[0]
159+
ifverbose:
160+
print(
161+
"after",self.position,next_positions,closest_positions,target,self
162+
)
163+
164+
self.position=target
165+
166+
defattack(self,creatures):
167+
"""
168+
Attacks an ennemy in range
169+
170+
:param Graph graph: The game map
171+
:param list creatures: A list of creatures
172+
:return: Nothing
173+
"""
174+
175+
# Find who to attack
176+
ennemies= [
177+
c
178+
forcincreatures
179+
fordirincomplex_utils.directions_straight
180+
ifself.position+dir==c.positionandc.type!=self.typeandc.alive
181+
]
182+
ifnotennemies:
183+
return
184+
185+
min_HP_ennemies=player_sort(
186+
[eforeinennemiesife.HP==min([e.HPforeinennemies])]
187+
)
188+
ennemy=player_sort(min_HP_ennemies)[0]
189+
190+
ennemy.lose_HP(self.attack_power)
191+
192+
deflose_HP(self,HP):
193+
"""
194+
Loses HP following an attack
195+
196+
:param int HP: How many HP to lose
197+
:return: Nothing
198+
"""
199+
self.HP-=HP
200+
self.alive=self.HP>0
201+
202+
203+
defplayer_sort(players):
204+
players.sort(key=lambdaa: (-a.position.imag,a.position.real))
205+
returnplayers
206+
207+
208+
# -------------------------------- Actual code execution ----------------------------- #
209+
210+
211+
ifpart_to_test==1:
212+
grid=puzzle_input
213+
214+
# Initial grid with everything
215+
graph=pathfinding.Graph()
216+
graph.grid_to_vertices(grid)
217+
218+
# Identify all creatures
219+
creatures=graph.grid_search(grid, ("E","G"))
220+
221+
creatures= [
222+
Player(type,position)fortypeincreaturesforpositionincreatures[type]
223+
]
224+
factions=set(c.typeforcincreatures)
225+
226+
round=0
227+
ifverbose_level>=2:
228+
print("Start")
229+
print(graph.vertices_to_grid({c.position:c.typeforcincreatures}))
230+
print([(c.type,c.position,c.HP)forcinplayer_sort(creatures)])
231+
whileTrue:
232+
player_sort(creatures)
233+
fori,creatureinenumerate(creatures):
234+
ifnotcreature.alive:
235+
continue
236+
creature.move(graph,creatures)
237+
creature.attack(creatures)
238+
239+
creatures= [cforcincreaturesifc.alive]
240+
factions=set(c.typeforcincreatures)
241+
iflen(factions)==1:
242+
break
243+
244+
round+=1
245+
ifverbose_level>=3:
246+
print("round",round)
247+
print(graph.vertices_to_grid({c.position:c.typeforcincreatures}))
248+
print([(c.type,c.position,c.HP,c.alive)forcinplayer_sort(creatures)])
249+
250+
ifverbose_level>=2:
251+
print("End of combat")
252+
print(graph.vertices_to_grid({c.position:c.typeforcincreatures}))
253+
print([(c.type,c.position,c.HP)forcinplayer_sort(creatures)])
254+
print(
255+
"Reached round:",
256+
round,
257+
"- Remaining HP:",
258+
sum(c.HPforcincreatures),
259+
"- Winner:",
260+
factions,
261+
)
262+
puzzle_actual_result=sum(c.HPforcincreaturesifc.alive)*round
263+
264+
265+
else:
266+
grid=puzzle_input
267+
268+
# Initial grid with everything
269+
graph=pathfinding.Graph()
270+
graph.grid_to_vertices(grid)
271+
272+
# Identify all creatures
273+
creatures_positions=graph.grid_search(grid, ("E","G"))
274+
275+
forattackinrange(3,100):
276+
creatures= [
277+
Player(type,position,attack)
278+
fortypeincreatures_positions
279+
forpositionincreatures_positions[type]
280+
]
281+
factions=set(c.typeforcincreatures)
282+
dead_elves=0
283+
284+
round=0
285+
whiledead_elves==0:
286+
player_sort(creatures)
287+
fori,creatureinenumerate(creatures):
288+
ifnotcreature.alive:
289+
continue
290+
creature.move(graph,creatures)
291+
creature.attack(creatures)
292+
293+
dead_elves=len([cforcincreaturesifc.type=="E"andnotc.alive])
294+
creatures= [cforcincreaturesifc.alive]
295+
factions=set(c.typeforcincreatures)
296+
iflen(factions)==1:
297+
break
298+
299+
round+=1
300+
301+
ifverbose_level>=2:
302+
print("End of combat with attack",attack)
303+
ifverbose_level>=3:
304+
print(graph.vertices_to_grid({c.position:c.typeforcincreatures}))
305+
print(
306+
"Reached round:",
307+
round,
308+
"- Remaining HP:",
309+
sum(c.HPforcincreatures),
310+
"- Winner:",
311+
factions,
312+
)
313+
print("Dead elves:",dead_elves)
314+
315+
iffactions==set("E",):
316+
puzzle_actual_result=sum(c.HPforcincreaturesifc.alive)*round
317+
break
318+
319+
# -------------------------------- Outputs / results -------------------------------- #
320+
321+
print("Expected result : "+str(puzzle_expected_result))
322+
print("Actual result : "+str(puzzle_actual_result))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp