solver.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. #!/usr/bin/python3
  2. import sys
  3. #i love aocd.
  4. from aocd import get_data
  5. from aocd import submit
  6. ### SHORTCUTS
  7. def intify(str_list):
  8. """
  9. Takes a list of stings that are assumed to refer to integers and returns a list of integers.
  10. """
  11. return [int(item) for item in str_list]
  12. ### REFS
  13. values = { # i'm not sorry for this at all.
  14. 'a':1,
  15. 'b':2,
  16. 'c':3,
  17. 'd':4,
  18. 'e':5,
  19. 'f':6,
  20. 'g':7,
  21. 'h':8,
  22. 'i':9,
  23. 'j':10,
  24. 'k':11,
  25. 'l':12,
  26. 'm':13,
  27. 'n':14,
  28. 'o':15,
  29. 'p':16,
  30. 'q':17,
  31. 'r':18,
  32. 's':19,
  33. 't':20,
  34. 'u':21,
  35. 'v':22,
  36. 'w':23,
  37. 'x':24,
  38. 'y':25,
  39. 'z':26,
  40. 'A':27,
  41. 'B':28,
  42. 'C':29,
  43. 'D':30,
  44. 'E':31,
  45. 'F':32,
  46. 'G':33,
  47. 'H':34,
  48. 'I':35,
  49. 'J':36,
  50. 'K':37,
  51. 'L':38,
  52. 'M':39,
  53. 'N':40,
  54. 'O':41,
  55. 'P':42,
  56. 'Q':43,
  57. 'R':44,
  58. 'S':45,
  59. 'T':46,
  60. 'U':47,
  61. 'V':48,
  62. 'W':49,
  63. 'X':50,
  64. 'Y':51,
  65. 'Z':52,
  66. }
  67. ### DAYS
  68. def day_one_solver():
  69. """
  70. Returns the answer for day 1.
  71. """
  72. loads = day_one_processor(get_data(day=1, year=2022).split("\n"))
  73. p1 = loads[-1]
  74. p2 = loads[-1] + loads[-2] + loads[-3]
  75. return p1, p2
  76. def day_one_processor(input):
  77. """
  78. Returns an int list of summed up pack loads.
  79. """
  80. loads = []
  81. load = 0
  82. for x in input:
  83. if x:
  84. load = load + int(x)
  85. else:
  86. loads.append(load)
  87. load = 0
  88. loads.sort()
  89. return loads
  90. def day_two_solver():
  91. """
  92. Returns the answer for day 2.
  93. """
  94. sample = ["A Y", "B X", "C Z"]
  95. data = get_data(day=2, year=2022).split("\n")
  96. return day_two_processor_a(data), day_two_processor_b(data)
  97. def day_two_processor_a(input):
  98. """
  99. Day 2 part A processor. I'm sure there's a tidier way to write this, but I
  100. did this fast.
  101. """
  102. score = 0
  103. for x in input:
  104. (elf, you)= x.split()
  105. if you == "X":
  106. score = score + 1
  107. if elf == "C":
  108. score = score + 6
  109. elif elf == "A":
  110. score = score + 3
  111. elif you == "Y":
  112. score = score + 2
  113. if elf == "A":
  114. score = score + 6
  115. elif elf == "B":
  116. score = score + 3
  117. else:
  118. score = score + 3
  119. if elf == "B":
  120. score = score + 6
  121. elif elf == "C":
  122. score = score + 3
  123. return score
  124. def day_two_processor_b(input):
  125. """
  126. Day 2 part B processor; yeah, naive.
  127. """
  128. score = 0
  129. for x in input:
  130. (elf, you)= x.split()
  131. if you == "X":
  132. if elf == "C":
  133. score = score + 2
  134. elif elf == "A":
  135. score = score + 3
  136. else:
  137. score = score + 1
  138. elif you == "Y":
  139. score = score + 3
  140. if elf == "A":
  141. score = score + 1
  142. elif elf == "B":
  143. score = score + 2
  144. else:
  145. score = score + 3
  146. else:
  147. score = score + 6
  148. if elf == "B":
  149. score = score + 3
  150. elif elf == "C":
  151. score = score + 1
  152. else:
  153. score = score + 2
  154. return score
  155. def day_three_solver():
  156. """
  157. Returns the answer for day 3.
  158. """
  159. sample = ["vJrwpWtwJgWrhcsFMMfFFhFp",
  160. "jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL",
  161. "PmmdzqPrVvPwwTWBwg",
  162. "wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn",
  163. "ttgJtRGJQctTZtZT",
  164. "CrZsJsPPZsGzwwsLwLmpwMDw"]
  165. data = get_data(day=3, year=2022).split("\n")
  166. p1 = day_three_processor_a(data)
  167. p2 = day_three_processor_b(data)
  168. return p1, p2
  169. def day_three_processor_a(input):
  170. score = 0
  171. for x in input:
  172. dup = ""
  173. items = list(x)
  174. half = int(len(items)/2)
  175. for y in items[0:half]:
  176. if y in items[half:]:
  177. dup = y
  178. score = score + values.get(dup)
  179. return score
  180. def day_three_processor_b(input):
  181. """
  182. weeee iterating
  183. """
  184. score = 0
  185. index = 0
  186. count = 3
  187. for x in input:
  188. if count % 3 == 0:
  189. dup = ""
  190. items = list(x)
  191. for y in items:
  192. if y in list(input[index+1]) and y in list(input[index+2]):
  193. dup = y
  194. print(dup)
  195. score = score + values.get(dup)
  196. index = index + 1
  197. count = count + 1
  198. else:
  199. index = index + 1
  200. count = count + 1
  201. continue
  202. return score
  203. def day_four_solver():
  204. """
  205. Returns the answer for day 4.
  206. """
  207. sample = ["2-4,6-8", "2-3,4-5", "5-7,7-9", "2-8,3-7", "6-6,4-6", "2-6,4-8"]
  208. data = get_data(day=4, year=2022).split("\n")
  209. p1 = day_four_processor_a(data)
  210. p2 = day_four_processor_b(data)
  211. return p1, p2
  212. def day_four_processor_a(input):
  213. """
  214. do you know how long i took me to realize i forgot to intify and was
  215. comparing strings, python, is very dirty
  216. """
  217. ans = 0
  218. for pair in input:
  219. pairs = pair.split(",")
  220. a = intify(pairs[0].split("-"))
  221. b = intify(pairs[1].split("-"))
  222. if a[0] >= b[0] and a[0] <= b[1]:
  223. if a[1] <= b[1]:
  224. ans = ans +1
  225. elif a[0] == b[0]:
  226. if b[1] <= a[1]:
  227. ans = ans +1
  228. elif b[0] >= a[0] and b[0] <= a[1]:
  229. if b[1] <= a[1]:
  230. ans = ans +1
  231. return ans
  232. def day_four_processor_b(input):
  233. """
  234. wow this took me a lot of staring before i realized it was totally trivial.
  235. """
  236. ans = 0
  237. for pair in input:
  238. pairs = pair.split(",")
  239. a = intify(pairs[0].split("-"))
  240. b = intify(pairs[1].split("-"))
  241. if a[0] >= b[0] and a[0] <= b[1]:
  242. ans = ans +1
  243. elif b[0] >= a[0] and b[0] <= a[1]:
  244. ans = ans +1
  245. return ans
  246. def day_five_solver():
  247. """
  248. today i was like, fuck it, i'm not parsing that shit, and hand-typed in all
  249. the stacks. this means i cannot trivially repeat this with other input
  250. without looking at it and hand-typing and hardcoding in slices.
  251. one of those days where implementing part b is actually more
  252. straightforward for me than part a, but probably because i did all the work
  253. in a way that made it easily reused.
  254. did a couple passes on tidying up the code after submission. i could do the
  255. honorable thing and write out a full input parser for my own health, but
  256. also, the star awarding doesn't care how you get the right answer, and i
  257. have only so many minutes in my life.
  258. """
  259. s_data = """ [D]
  260. [N] [C]
  261. [Z] [M] [P]
  262. 1 2 3
  263. move 1 from 2 to 1
  264. move 3 from 1 to 3
  265. move 2 from 2 to 1
  266. move 1 from 1 to 2""".split("\n")[5:]
  267. s_stack = ["ZN", "MCD", "P"]
  268. data = get_data(day=5, year=2022).split("\n")[10:]
  269. stack = ["VCDRZGBW", "GWFCBSTV", "CBSNW", "QGMNJVCP", "TSLFDHB", "JVTWMN",
  270. "PFLCSTG", "BDZ", "MNZW"]
  271. p1, p2 = "",""
  272. codes = get_instructions(data)
  273. for x in codes: # instructions are 1-indexed
  274. stack = crane_it_a(x[0], x[1]-1, x[2]-1, stack)
  275. for x in stack:
  276. p1 += x[-1]
  277. ## reset the stack for part b WAIT WHY DO I SOMETIMES SAY PART B AND
  278. ## SOMETIMES SAY P2
  279. stack = ["VCDRZGBW", "GWFCBSTV", "CBSNW", "QGMNJVCP", "TSLFDHB", "JVTWMN",
  280. "PFLCSTG", "BDZ", "MNZW"]
  281. for x in codes: # lol watch your off-by-ones
  282. stack = crane_it_b(x[0]-1, x[1]-1, x[2]-1, stack)
  283. for x in stack:
  284. p2 += x[-1]
  285. return p1, p2
  286. def get_instructions(data):
  287. """
  288. just parsing out the instructions and returning a list of integers
  289. """
  290. codes = []
  291. for line in data:
  292. ins = line.split(" ")
  293. codes.append(intify([ins[1], ins[3], ins[5]]))
  294. return codes
  295. def crane_it_a(reps, start, end, stack):
  296. """
  297. im still so proud of myself for knowing how to do a good recurse!!!
  298. """
  299. if reps > 0:
  300. stack[end] += stack[start][-1]
  301. stack[start] = stack[start][0:-1]
  302. return crane_it_a(reps-1, start, end, stack)
  303. return stack
  304. def crane_it_b(reps, start, end, stack):
  305. """
  306. so boring no recusion
  307. """
  308. stack[end] += stack[start][-1-reps:]
  309. stack[start] = stack[start][0:-1-reps]
  310. return stack
  311. def day_six_solver():
  312. """
  313. wow this was....very easy???? had to swat some typos for p2 because i'm
  314. sreepy.
  315. did a quick pass to tidy up the processor.
  316. """
  317. s_data = "mjqjpqmgbljsphdztnvjfqwrcgsmlb"
  318. s_data2 = "bvwbjplbgvbhsrlpgdmjqwftvncz"
  319. data = get_data(day=6, year=2022)
  320. p1, p2 = "",""
  321. p1 = day_six_processor(data, 4)
  322. p2 = day_six_processor(data, 14)
  323. return p1, p2
  324. def day_six_processor(input, length):
  325. ans = 0
  326. a = 0
  327. b = length
  328. for i in range (len(input)-length-1):
  329. chunk = input[a:b]
  330. if len(set(chunk)) == length:
  331. return i+length
  332. a += 1
  333. b += 1
  334. return ans
  335. def day_seven_solver():
  336. """
  337. oh my god parser hell
  338. i got stuck on p2 all day because i was returning the name of the directory
  339. and not the size. oops.
  340. did a little cleanup post-star.
  341. """
  342. s_data = """$ cd /
  343. $ ls
  344. dir a
  345. 14848514 b.txt
  346. 8504156 c.dat
  347. dir d
  348. $ cd a
  349. $ ls
  350. dir e
  351. 29116 f
  352. 2557 g
  353. 62596 h.lst
  354. $ cd e
  355. $ ls
  356. 584 i
  357. $ cd ..
  358. $ cd ..
  359. $ cd d
  360. $ ls
  361. 4060174 j
  362. 8033020 d.log
  363. 5626152 d.ext
  364. 7214296 k""".split("\n")
  365. data = get_data(day=7, year=2022).split("\n")
  366. p1, p2 = "",""
  367. root, all_dirs = day_seven_parser(data)
  368. p1 = day_seven_processor_a(all_dirs)
  369. p2 = day_seven_processor_b(root, all_dirs)
  370. return p1, p2
  371. class Directory:
  372. def __init__(self, name):
  373. self.name = name
  374. self.dirs = {}
  375. self.size = 0
  376. def add_file(self, filesize):
  377. self.size += filesize
  378. def add_dir(self, dir_name, dir):
  379. self.dirs.update({dir_name: dir})
  380. def get_size(self):
  381. return self.size
  382. def get_name(self):
  383. return self.name
  384. def get_dir(self, dir_name):
  385. return self.dirs.get(dir_name)
  386. def day_seven_parser(input):
  387. home = Directory("root")
  388. here = home
  389. last = []
  390. all_dirs = []
  391. for i in range(len(input) - 1):
  392. line = input[i]
  393. if line[0] == "$":
  394. cmd = line.split(" ")[1:]
  395. if cmd[0] == "ls":
  396. ls = []
  397. ## slurp up all the ls output
  398. for j in range(i+1, len(input)):
  399. if input[j][0] != "$":
  400. ls.append(input[j])
  401. else:
  402. break
  403. for item in ls:
  404. if item[0] == 'd':
  405. dir = item.split(" ")[1]
  406. new = Directory(dir)
  407. here.add_dir(dir, new)
  408. all_dirs.append(new)
  409. else:
  410. filesize = int(item.split(" ")[0])
  411. here.add_file(filesize)
  412. for parent in last:
  413. parent.add_file(filesize)
  414. elif cmd[0] == "cd":
  415. if cmd[1] == "..":
  416. here = last.pop()
  417. elif cmd[1] == "/":
  418. here = home
  419. last = []
  420. else:
  421. last.append(here)
  422. here = here.get_dir(cmd[1])
  423. return home, all_dirs
  424. def day_seven_processor_a(all_dirs):
  425. ans = 0
  426. for x in all_dirs:
  427. a = x.get_size()
  428. if x.get_size() <= 100000:
  429. ans += x.get_size()
  430. return ans
  431. def day_seven_processor_b(root, all_dirs):
  432. disk = 70000000
  433. needed = 30000000
  434. free = disk - root.get_size()
  435. delta = needed - free
  436. curr = disk
  437. for x in all_dirs:
  438. a = x.get_size()
  439. if a >= delta:
  440. if a < curr:
  441. curr = a
  442. return curr
  443. def day_eight_solver():
  444. """
  445. whew finicky matrix shit.
  446. """
  447. s_data = """30373
  448. 25512
  449. 65332
  450. 33549
  451. 35390""".split("\n")
  452. data = get_data(day=8, year=2022).split("\n")
  453. p1, p2 = "",""
  454. p1 = day_eight_processor_a(data)
  455. p2 = day_eight_processor_b(data)
  456. return p1, p2
  457. def day_eight_processor_a(data):
  458. grid = []
  459. for line in data:
  460. grid.append(intify(list(line)))
  461. visible = len(grid[0]) * 2 + len(grid) * 2 - 4
  462. for row in range(1, len(grid[0])-1):
  463. x = list(grid[row])
  464. for column in range(1, len(x)-1):
  465. y = list(x)[column]
  466. if is_visible(row, column, grid):
  467. visible += 1
  468. return visible
  469. def is_visible(row, column, grid):
  470. this = grid[row][column]
  471. ans = False
  472. for i in range(0, row):
  473. if grid[i][column] >= this:
  474. ans = False
  475. break
  476. else:
  477. ans = True
  478. if ans:
  479. return True
  480. for i in range(row+1, len(grid[row])):
  481. if grid[i][column] >= this:
  482. ans = False
  483. break
  484. else:
  485. ans = True
  486. if ans:
  487. return True
  488. for i in range(0, column):
  489. if grid[row][i] >= this:
  490. ans = False
  491. break
  492. else:
  493. ans = True
  494. if ans:
  495. return True
  496. for i in range(column+1, len(grid)):
  497. if grid[row][i] >= this:
  498. ans = False
  499. break
  500. else:
  501. ans = True
  502. return ans
  503. def day_eight_processor_b(data):
  504. grid = []
  505. for line in data:
  506. grid.append(intify(list(line)))
  507. best = 0
  508. for row in range(1, len(grid[0])-1):
  509. x = list(grid[row])
  510. for column in range(1, len(x)-1):
  511. y = list(x)[column]
  512. score = calc_score(row, column, grid)
  513. if score > best:
  514. best = score
  515. return best
  516. def calc_score(row, column, grid):
  517. this = grid[row][column]
  518. (u, d, l, r) = 0, 0, 0, 0,
  519. for i in range(row-1, -1, -1): # UP
  520. u += 1
  521. if grid[i][column] >= this:
  522. break
  523. for i in range(row+1, len(grid[row])): # DOWN
  524. d += 1
  525. if grid[i][column] >= this:
  526. break
  527. for i in range(column-1, -1, -1): # LEFT
  528. l += 1
  529. if grid[row][i] >= this:
  530. break
  531. for i in range(column+1, len(grid)): # RIGHT
  532. r += 1
  533. if grid[row][i] >= this:
  534. break
  535. return u * d * l * r
  536. def day_nine_solver():
  537. """
  538. """
  539. s_data = """R 4
  540. U 4
  541. L 3
  542. D 1
  543. R 4
  544. D 1
  545. L 5
  546. R 2""".split("\n")
  547. data = get_data(day=9, year=2022).split("\n")
  548. p1, p2 = "",""
  549. p1 = day_nine_processor_a(data)
  550. #p2 = day_nine_processor_b(data)
  551. return p1, p2
  552. def day_nine_processor_a(data):
  553. visited = []
  554. H = (0,0)
  555. T = (0,0)
  556. for inst in data:
  557. print(inst)
  558. dir, steps = inst.split(" ")
  559. ## process head movement
  560. for x in range(0, int(steps)):
  561. if dir == "U":
  562. H = (H[0]+1, H[1])
  563. if dir == "D":
  564. H = (H[0]-1, H[1])
  565. if dir == "L":
  566. H = (H[0], H[1]-1)
  567. if dir == "R":
  568. H = (H[0], H[1]+1)
  569. print("before scoots")
  570. print("H: {}".format(H))
  571. print("T: {}".format(T))
  572. ## process tail movement
  573. if T not in visited:
  574. visited.append(T)
  575. if T == H:
  576. print("overlap")
  577. continue
  578. elif T[0] == H[0] and abs(T[1] - H[1]) == 1:
  579. print("adjacent")
  580. continue
  581. elif T[1] == H[1] and abs(T[0] - H[0]) == 1:
  582. print("adjacent")
  583. continue
  584. elif abs(T[0] - H[0]) == 1 and abs(T[1] - H[1]) == 1:
  585. print("kitty")
  586. elif T[0] == H[0]:
  587. ## LR scoots
  588. print("LR scoot")
  589. if H[1] > T[1]:
  590. ## scoot right
  591. T = (T[0], T[1] + 1)
  592. else:
  593. ## scoot left
  594. T = (T[0], T[1] - 1)
  595. elif T[1] == H[1]:
  596. ## UD scoots
  597. print("UD scoot")
  598. if H[0] > T[0]:
  599. ## scoot up
  600. T = (T[0] + 1, T[1])
  601. else:
  602. ## scoot down
  603. T = (T[0] - 1, T[1])
  604. else:
  605. ## diagonal scoots
  606. print("diagonal scoot")
  607. if (H[0] - T[0]) > 1:
  608. if H[1] > T[1]:
  609. ## scoot UR
  610. T = (T[0] + 1, T[1] + 1)
  611. else:
  612. ## scoot DR
  613. T = (T[0] + 1, T[1] - 1)
  614. elif (H[0] - T [0]) < 1:
  615. if H[1] > T[1]:
  616. ## scoot UL
  617. T = (T[0] - 1, T[1] + 1)
  618. else:
  619. ## scoot DL
  620. T = (T[0] - 1, T[1] - 1)
  621. elif (H[1] - T [1]) > 1:
  622. if H[0] > T[0]:
  623. ## scoot UR
  624. T = (T[0] + 1, T[1] + 1)
  625. else:
  626. ## scoot UL
  627. T = (T[0] - 1, T[1] + 1)
  628. elif (H[1] - T [1]) < 1:
  629. if H[0] > T[0]:
  630. ## scoot DR
  631. T = (T[0] + 1, T[1] - 1)
  632. else:
  633. ## scoot DL
  634. T = (T[0] - 1, T[1] - 1)
  635. print("after scoots")
  636. print("H: {}".format(H))
  637. print("T: {}".format(T))
  638. print(visited)
  639. return len(visited)
  640. def day_nine_processor_b(data):
  641. return 0
  642. if __name__ == '__main__':
  643. #day1 = day_one_solver()
  644. #print("day 01: {}".format(day1))
  645. #submit(day1[0], part="a", day=1, year=2022)
  646. #submit(day1[1], part="b", day=1, year=2022)
  647. #day2 = day_two_solver()
  648. #print("day 02: {}".format(day2))
  649. #submit(day2[0], part="a", day=2, year=2022)
  650. #submit(day2[1], part="b", day=2, year=2022)
  651. #day3 = day_three_solver()
  652. #print("day 03: {}".format(day3))
  653. #submit(day3[0], part="a", day=3, year=2022)
  654. #submit(day3[1], part="b", day=3, year=2022)
  655. #day4 = day_four_solver()
  656. #print("day 04: {}".format(day4))
  657. #submit(day4[0], part="a", day=4, year=2022)
  658. #submit(day4[1], part="b", day=4, year=2022)
  659. #day5 = day_five_solver()
  660. #print("day 05: {}".format(day5))
  661. #submit(day5[0], part="a", day=5, year=2022)
  662. #submit(day5[1], part="b", day=5, year=2022)
  663. #day6 = day_six_solver()
  664. #print("day 06: {}".format(day6))
  665. #submit(day6[0], part="a", day=6, year=2022)
  666. #submit(day6[1], part="b", day=6, year=2022)
  667. #day7 = day_seven_solver()
  668. #print("day 07: {}".format(day7))
  669. #submit(day7[0], part="a", day=7, year=2022)
  670. #submit(day7[1], part="b", day=7, year=2022)
  671. #day8 = day_eight_solver()
  672. #print("day 08: {}".format(day8))
  673. #submit(day8[0], part="a", day=8, year=2022)
  674. #submit(day8[1], part="b", day=8, year=2022)
  675. day9 = day_nine_solver()
  676. print("day 09: {}".format(day9))
  677. submit(day9[0], part="a", day=9, year=2022)
  678. #submit(day9[1], part="b", day=9, year=2022)