Nuolong's recent activity
-
Comment on Day 17: Conway Cubes in ~comp
-
Comment on Day 12: Rain Risk in ~comp
Nuolong Python Repo Link In short, I think I overcomplicated this relatively simple problem. I ended up using a dictionary to mark the ship/waypoint coordinates. I realized it would have been easier to...Python
Repo LinkIn short, I think I overcomplicated this relatively simple problem. I ended up using a dictionary to mark the ship/waypoint coordinates. I realized it would have been easier to just use cartesian coordinates but I decided to go this route anyway.
Part 1
I used a `pointing` variable to keep track of which direction the ship was facing. For moving the ship, I would add the value to the appropriate direction and subtract the value from the opposite. In the end, I was only interested in the absolute `E` and `N` values (which would be analogous to the `x` and `y` in a normal approach.#!/usr/bin/env python3 import sys DIRECTIONS = ['E', 'S', 'W', 'N'] def travel(dir_lst): status = {'E' : 0, 'S' : 0, 'W' : 0, 'N' : 0} pointing = 0 # East for dir in dir_lst: if dir[0] in DIRECTIONS: status[dir[0]] += dir[1] opposite = (DIRECTIONS.index(dir[0]) + 2) % len(DIRECTIONS) status[DIRECTIONS[opposite]] -= dir[1] elif dir[0] == 'L': pointing -= (dir[1] // 90) % len(DIRECTIONS) pointing %= len(DIRECTIONS) elif dir[0] == 'R': pointing += (dir[1] // 90) % len(DIRECTIONS) pointing %= len(DIRECTIONS) elif dir[0] == 'F': status[DIRECTIONS[pointing]] += dir[1] opposite = (pointing + 2) % len(DIRECTIONS) status[DIRECTIONS[opposite]] -= dir[1] print(abs(status['E']) + abs(status['N'])) def main(): dir_lst = [] for dir in sys.stdin: dir_lst.append((dir[0], int(dir[1:]))) travel(dir_lst) if __name__ == '__main__': main()
Part 2
I used a similar approach as part 1. As for rotating the waypoint, I just rotated the values of my dictionary manually.#!/usr/bin/env python3 import sys DIRECTIONS = ['E', 'S', 'W', 'N'] def travel(dir_lst): status = {'E' : 0, 'S' : 0, 'W' : 0, 'N' : 0} waypoint = {'E' : 10, 'S' : -1, 'W' : -10, 'N' : 1} for dir in dir_lst: if dir[0] in DIRECTIONS: waypoint[dir[0]] += dir[1] opposite = (DIRECTIONS.index(dir[0]) + 2) % len(DIRECTIONS) waypoint[DIRECTIONS[opposite]] -= dir[1] elif dir[0] == 'L': for _ in range(dir[1] // 90): temp_1 = waypoint['E'] waypoint['E'] = waypoint['S'] waypoint['S'] = waypoint['W'] waypoint['W'] = waypoint['N'] waypoint['N'] = temp_1 elif dir[0] == 'R': for _ in range(dir[1] // 90): temp_1 = waypoint['E'] waypoint['E'] = waypoint['N'] waypoint['N'] = waypoint['W'] waypoint['W'] = waypoint['S'] waypoint['S'] = temp_1 elif dir[0] == 'F': status['E'] += waypoint['E'] * dir[1] status['S'] += waypoint['S'] * dir[1] status['W'] += waypoint['W'] * dir[1] status['N'] += waypoint['N'] * dir[1] print(abs(status['E']) + abs(status['N'])) def main(): dir_lst = [] for dir in sys.stdin: dir_lst.append((dir[0], int(dir[1:]))) travel(dir_lst) if __name__ == '__main__': main()
-
Comment on Day 11: Seating System in ~comp
Nuolong Python I wasn't a big fan of this problem! My solutions are admittedly not the best, but they worked out in the end and they're easy for me to understand. Will definitely look forward to seeing...Python
I wasn't a big fan of this problem! My solutions are admittedly not the best, but they worked out in the end and they're easy for me to understand. Will definitely look forward to seeing others' better solutions. It was especially difficult for me to debug the program (in one instance, I was missing a critical rule in part B, like @PapaNachos wrote). My incompetent reading strikes again!Part 1
I padded the entire seating matrix with floors, just because I didn't want to have to deal with special cases for the edge seats. Though there probably is just be an entirely easier way to solve this problem, I decided to go with this. Then I used a boolean flag so that I could keep running my function until equilibrium.#!/usr/bin/env python3 import sys INPUT_COLS = 92 INPUT_ROWS = 99 # calculates new matrix of seats. marks if any changes were made def adjacents(seats): adj_mat = [['.' for _ in range(INPUT_COLS + 2)]] changed = False for i in range(1, INPUT_ROWS + 1): row = [] for j in range(1, INPUT_COLS + 1): count = 0 if seats[i-1][j-1] == '#': count += 1 if seats[i+1][j] == '#': count += 1 if seats[i+1][j-1] == '#': count += 1 if seats[i][j-1] == '#': count += 1 if seats[i][j+1] == '#': count += 1 if seats[i-1][j] == '#': count += 1 if seats[i-1][j+1] == '#': count += 1 if seats[i+1][j+1] == '#': count += 1 if seats[i][j] == 'L' and not count: row.append('#') changed = True elif seats[i][j] == '#' and count >= 4: row.append('L') changed = True else: row.append(seats[i][j]) adj_mat.append(["."] + row + ["."]) adj_mat.append(['.' for _ in range(INPUT_COLS + 2)]) return adj_mat, changed # count num of occupied seats def count_occ(seats): count = 0 for i in range(1, INPUT_ROWS + 1): for j in range(1, INPUT_COLS + 1): if seats[i][j] == '#': count += 1 return count def main(): # read input into 2D matrix, pad it with "floor" seats = [['.' for _ in range(INPUT_COLS + 2)]] for _ in range(INPUT_ROWS): seats.append(["."] + list(sys.stdin.readline().strip()) + ["."]) seats.append(['.' for _ in range(INPUT_COLS + 2)]) # flag changed = True while changed: seats, changed = adjacents(seats) print(count_occ(seats)) if __name__ == '__main__': main()
Part 2
A similar approach to part 1 with padding and a flag system for handling the equilibrium. The important rule I missed was in regards to how an empty seat blocks off the sight of an occupied seat. As a result, I wasted time trying to debug my program.#!/usr/bin/env python3 import sys INPUT_COLS = 92 INPUT_ROWS = 99 # calculates new matrix of seats. marks if any changes were made def sights(seats): adj_mat = [['.' for _ in range(INPUT_COLS + 2)]] changed = False for i in range(1, INPUT_ROWS + 1): row = [] for j in range(1, INPUT_COLS + 1): count = 0 # nw x = i - 1 y = j - 1 while x and y: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break x -= 1 y -= 1 # n x = i - 1 y = j while x: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break x -= 1 # ne x = i - 1 y = j + 1 while x and y != INPUT_COLS + 1: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break x -= 1 y += 1 # e x = i y = j + 1 while y != INPUT_COLS + 1: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break y += 1 # se x = i + 1 y = j + 1 while x != INPUT_ROWS + 1 and y != INPUT_COLS + 1: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break x += 1 y += 1 # s x = i + 1 y = j while x != INPUT_ROWS + 1: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break x += 1 # sw x = i + 1 y = j - 1 while x != INPUT_ROWS + 1 and y: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break x += 1 y -= 1 # w x = i y = j - 1 while y: if seats[x][y] == "L": break elif seats[x][y] == "#": count += 1 break y -= 1 if seats[i][j] == 'L' and not count: row.append('#') changed = True elif seats[i][j] == '#' and count >= 5: row.append('L') changed = True else: row.append(seats[i][j]) adj_mat.append(["."] + row + ["."]) adj_mat.append(['.' for _ in range(INPUT_COLS + 2)]) return adj_mat, changed # count num of occupied seats def count_occ(seats): count = 0 for i in range(1, INPUT_ROWS + 1): for j in range(1, INPUT_COLS + 1): if seats[i][j] == '#': count += 1 return count def main(): # read input into 2D matrix, pad it with "floor" seats = [['.' for _ in range(INPUT_COLS + 2)]] for _ in range(INPUT_ROWS): seats.append(["."] + list(sys.stdin.readline().strip()) + ["."]) seats.append(['.' for _ in range(INPUT_COLS + 2)]) # flag changed = True while changed: seats, changed = sights(seats) print(count_occ(seats)) if __name__ == '__main__': main()
-
Comment on Day 10: Adapter Array in ~comp
Nuolong This problem was really confusing for me to understand at first, though what it was actually asking wasn't complicated. Shows how much I need to improve my reading comprehension. Repo link Part 1...This problem was really confusing for me to understand at first, though what it was actually asking wasn't complicated. Shows how much I need to improve my reading comprehension.
Part 1
Standard, manual counting#!/usr/bin/env python3 import sys def find_jolts(nums): diff_1 = 0 diff_3 = 1 # for last-to built-in joltage start = 0 while nums: curr = nums.pop(0) if start + 1 == curr: diff_1 += 1 start = curr elif start + 3 == curr: diff_3 += 1 start = curr return diff_1 * diff_3 def main(): nums = [] for num in sys.stdin: nums.append(int(num)) nums.sort() print(find_jolts(nums)) if __name__ == '__main__': main()
Part 2
Solution using memoization.#!/usr/bin/env python3 import sys def count_seq(n, nums): mem = [0] * (n + 1) mem[0] = 1 for i in nums: mem[i] = mem[i - 1] + mem[i - 2] + mem[i - 3] return mem[n] def main(): nums = [] for num in sys.stdin: nums.append(int(num)) nums.sort() print(count_seq(max(nums), nums)) if __name__ == '__main__': main()
-
Comment on Day 9: Encoding Error in ~comp
Nuolong (edited )LinkPython The problem was a little boring in my opinion today... but backstory made it interesting nonetheless! Repo Link Part 2 #!/usr/bin/env python3 import sys def find_ctg(window, invalid_num):...Python
The problem was a little boring in my opinion today... but backstory made it interesting nonetheless!Part 2
#!/usr/bin/env python3 import sys def find_ctg(window, invalid_num): curr_sum = window[0] start = 0 end = 1 while end < len(window) - 1: # front window value is removed from window while curr_sum > invalid_num and start < end: curr_sum -= window[start] start += 1 # contiguous subarray found if curr_sum == invalid_num: sub_arr = window[start:end+1] return max(sub_arr) + min(sub_arr) # new value added to end of window else: curr_sum += window[end] end += 1 def abide(window, n): for i, w_n in enumerate(window): diff = n - w_n if diff in window[i + 1:]: return True return False def find_rulebreaker(nums, preamble_len): window = nums[0:preamble_len] strt_remain = nums[preamble_len:] for i, n in enumerate(strt_remain): if (abide(window, n)): window.append(n) window.pop(0) else: return i, n def main(): nums = [] for num in sys.stdin: nums.append(int(num)) i, invalid_num = find_rulebreaker(nums, 25) print(find_ctg(nums[:i], invalid_num)) if __name__ == '__main__': main()
-
Comment on Day 8: Handheld Halting in ~comp
Nuolong I believe I had really mediocre approaches which led me to make a lot of mistakes on my way to the solution, but I got the solution nevertheless! (That's my holiday spirit) Repo link Part 1 Here I...I believe I had really mediocre approaches which led me to make a lot of mistakes on my way to the solution, but I got the solution nevertheless! (That's my holiday spirit)
Repo linkPart 1
Here I edited the list's instruction itself to mark that it was already visited. I don't know what made me think of doing it this really odd way, but it messed me up a bit for part 2.#!/usr/bin/env python3 import sys def follow(instr): current = 0 acc = 0 while instr[current][0] != 'DID': if instr[current][0] == 'nop': instr[current][0] = "DID" current += 1 elif instr[current][0] == 'acc': acc += instr[current][1] instr[current][0] = "DID" current += 1 elif instr[current][0] == 'jmp': instr[current][0] = "DID" current += instr[current][1] return acc def main(): instr = [] for line in sys.stdin: instr.append(line.strip().split()) instr[-1][1] = int(instr[-1][1]) print(follow(instr)) if __name__ == '__main__': main()
Part 2
Kind of a mess, but it works. I ran into a problem when I used my part 1 `follow` and realized the program would stop running because it was reusing the same list of instructions that were renamed to mark they were visited on a previous iteration. So I went a simpler route and just marked a list instead for my visited instructions.#!/usr/bin/env python3 import sys def follow(instr): visited = [] current = 0 acc = 0 while current not in visited: if current == len(instr) - 1: return acc, current if instr[current][0] == 'nop': visited.append(current) current += 1 elif instr[current][0] == 'acc': acc += instr[current][1] visited.append(current) current += 1 elif instr[current][0] == 'jmp': visited.append(current) current += instr[current][1] return acc, current def find_success(instr): finish = len(instr) - 1 for i in instr: if i[0] == 'nop': i[0] = 'jmp' acc, fin = follow(instr) if fin == finish: return acc i[0] = 'nop' elif i[0] == 'jmp': i[0] = 'nop' acc, fin = follow(instr) i[0] = 'jmp' if fin == finish: return acc def main(): instr = [] for line in sys.stdin: instr.append(line.strip().split()) instr[-1][1] = int(instr[-1][1]) print(find_success(instr)) if __name__ == '__main__': main()
-
Comment on Day 7: Handy Haversacks in ~comp
Nuolong Quite a novice at programming in general, having lots of fun doing this so far! This one was definitely a lot more challenging to me than previous days so far. I should start using defaultdict,...Quite a novice at programming in general, having lots of fun doing this so far! This one was definitely a lot more challenging to me than previous days so far. I should start using
defaultdict
, haha.
Python
Repo linkPart 1
#!/usr/bin/env python3 import sys import re OUTER_COLOR = r'([a-z]+ [a-z]+) bags contain' INNER_COLOR = r'(?: (\d+) ([a-z]+ [a-z]+) bags?[,.])' has_shiny_gold = set() def shiny_gold(has_bag, color): global has_shiny_gold if color in has_bag: for clr in has_bag[color]: try: has_shiny_gold.add(clr) except KeyError: has_shiny_gold = {clr} shiny_gold(has_bag, clr) def main(): has_bag = {} count = 0 for line in sys.stdin: outer_color = re.findall(OUTER_COLOR, line)[0] for inner_count, inner_color in re.findall(INNER_COLOR, line): try: has_bag[inner_color].add(outer_color) except KeyError: has_bag[inner_color] = {outer_color} shiny_gold(has_bag, "shiny gold") print(len(has_shiny_gold)) if __name__ == '__main__': main()
Part 2
#!/usr/bin/env python3 import sys import re OUTER_COLOR = r'([a-z]+ [a-z]+) bags contain' INNER_COLOR = r'(?: (\d+) ([a-z]+ [a-z]+) bags?[,.])' def bags_needed(bags_inside, color): count = 0 if color in bags_inside: for bag, num in bags_inside[color]: count += int(num) + (int(num) * bags_needed(bags_inside, bag)) return count def main(): bags_inside = {} count = 0 for line in sys.stdin: outer_color = re.findall(OUTER_COLOR, line)[0] for inner_count, inner_color in re.findall(INNER_COLOR, line): try: bags_inside[outer_color].add((inner_color, inner_count)) except KeyError: bags_inside[outer_color] = {(inner_color, inner_count)} print(bags_needed(bags_inside, "shiny gold")) if __name__ == '__main__': main()
Python
Repo Link
I really didn't feel like doing this problem at first, but it was nice to get through it without much debugging at all. The hardest part was starting, though something even harder would be writing faster code! Behold my beautiful nested for loop code! Part 1 runs in about a second, while Part 2 runs in ~2 minutes.
Part 2
Part 1 can be seen in my repo link. Didn't post it because it would be redundant. I just made a dictionary where key values were tuples of the coordinates, and values were either inactive ('.') or active ('#'). That's how I inserted the input. For the function I just brute force iterated through all coordinates to find each of their neighbor counts and change their values accordingly to the rules. For the hard-coded ranges (-15 to 15), I was just too lazy to do the math to find the most appropriate bounds. So I picked a high-enough number that would simulate the infinite bounds given the number of cycles we had to run.Overall there's clearly a faster + smarter way to go about it. Like keeping track of only active cubes and their respective numbers of active neighbors, instead of iterating through all coordinates where I'm doing a lot of unnecessary comparisons. However, I just wanted to be done with this problem :)