V tretji nalogi je podan zemljevid gozda.
..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#
To je zgolj začetek - isti vzorec se še velikokrat ponovi proti desni. Z zgornjega levega oglišča se spustimo desno dol, tako da gremo v vsakem koraku vrstico nižje in tri znake desno.
O.##.........##.........##.........##.........##.........##....... --->
#..O#...#..#...#...#..#...#...#..#...#...#..#...#...#..#...#...#..
.#....X..#..#....#..#..#....#..#..#....#..#..#....#..#..#....#..#.
..#.#...#O#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#
.#...##..#..X...##..#..#...##..#..#...##..#..#...##..#..#...##..#.
..#.##.......#.X#.......#.##.......#.##.......#.##.......#.##..... --->
.#.#.#....#.#.#.#.O..#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#
.#........#.#........X.#........#.#........#.#........#.#........#
#.##...#...#.##...#...#.X#...#...#.##...#...#.##...#...#.##...#...
#...##....##...##....##...#X....##...##....##...##....##...##....#
.#..#...#.#.#..#...#.#.#..#...X.#.#..#...#.#.#..#...#.#.#..#...#.# --->
Znaki O
in X
predstavljajo našo pot -
O
pomeni proste celice, X
pa tiste, kjer
zadanemo drevo. Zanima nas, koliko dreves bomo podrli.
Branje je trivialno.
= [x.strip() for x in open("input.txt")] forest
Zdaj pa spust. Naredili bomo zanko čez vrstice,
for line in forest
. Poleg tega bomo hranili tudi koordinato
y
, saj je iz nje trivialno izračunati x
:
x = y * 3
. Koordinato y
bomo dobili kar z
enumerate
.
= 0
hits for y, line in enumerate(forest):
if line[y * 3] == "#":
+= 1
hits print(hits)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-27-eabe8b28dd4a> in <module>
1 hits = 0
2 for y, line in enumerate(forest):
----> 3 if line[y * 3] == "#":
4 hits += 1
5 print(hits)
IndexError: string index out of range
Seveda ne. y * 3
je hitro prevelik, gozd pa se ponavlja.
To, da "pridemo okoli" najlažje opišemo z ostankom pri deljenju
z dolžino vrstice.
= 0
n for y, line in enumerate(forest):
if line[y * 3 % len(line)] == "#":
+= 1
n print(n)
7
Po zgledu tega, kar smo se naučili ob prejšnji nalogi, spremenimo to
v vsoto: šteti želimo, kolikokrat je bil izraz
line[y * 3 % len(line)] == "#"
resničen, torej enak
True
(1
) in ne False
(0
).
Drugi del od nas zahteva, da preverimo različne smeri, konkretno
= [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)] directions
pri čemer prvo število pomeni dolžino pomika navzdol, drugi dolžino pomika desno.
Gornji program spremenimo v funkcijo in mu dodamo argumenta
dx
in dy
.
def hits(dx, dy, forest):
= 0
n for y, line in enumerate(forest[::dy]):
if line[y * dx % len(line)] == "#":
+= 1
n return n
3, 1, forest) hits(
7
Kam sta šla dx
in dy
? Za dx
je
očitno - nadomestil je trojko. dy
pa je razredčil gozd: s
forest[::dy]
poskrbimo, da bomo gledali samo vsako
dy
-to vrstico gozda.
Naloga pravi, da je potrebno izračunati število zadetih dreves za vsako od podanih smeri in to namnožiti skupaj.
= 1
product for dx, dy in directions:
*= hits(dx, dy, forest)
product print(product)
2431272960
Tako tole rešimo z generatorji.
Očitno bi bilo to mogoče natlačiti v eno samo vrstico. A to ni poanta. Tole je še vedno berljivo.
from functools import reduce
from operator import mul
= [x.strip() for x in open("input.txt")]
forest = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
directions
def hits(dx, dy, forest):
return sum(line[y * dx % len(line)] == "#"
for y, line in enumerate(forest[::dy]))
print(hits(3, 1, forest))
print(reduce(mul, (hits(dx, dy, forest) for dx, dy in directions)))
184
2431272960