Thursday, December 5, 2024

Advent of Code: Day 5

advent-of-code
Stephen Keane
Stephen Keane@skeane.io

Advent of Code: Day 5

Day5: Print Queue

Check out Print Queue for the day5 puzzle.

Part 1

Day 4 took me a while, so I was relived to find that day 5 was a faster for me to solve.

Part 1 Solution:

testPath = './testInput.txt'
inputPath = './input.txt'
chosenPath = inputPath

def parseInput(path):
  pageOrderingRules = []
  updates = []
  file = open(path, 'r')
  for line in file:
      if '|' in line:
          line = line.strip('
').split('|')
          line = list(map(int, line))
          pageOrderingRules.append(line)
      elif ',' in line:
          line = line.strip('
').split(',')
          line = list(map(int, line))
          updates.append(line)
  return pageOrderingRules, updates

pageOrderingRules, updates = parseInput(chosenPath)

def getValidUpdates(rules, updates):
  invalidUpdates = []
  updatesCopy = updates.copy()
  def getPrecedingPages(page, rules):
      precedingPages = []
      for before, after in rules:
          if after == page:
              precedingPages.append(before)
      return precedingPages
  def getFollowingPages(page, rules):
      followingPages = []
      for before, after in rules:
          if before == page:
              followingPages.append(after)
      return followingPages
  for update in updates:
      for pageSeq, page in enumerate(update):
          precedingPages = getPrecedingPages(page, rules)
          followingPages = getFollowingPages(page, rules)
          for precedingPage in precedingPages:
              if precedingPage in update[pageSeq:] and update.index(precedingPage) > pageSeq:
                  invalidUpdates.append(update)
                  break
          for followingPage in followingPages:
              if followingPage in update[:pageSeq] and update.index(followingPage) < pageSeq:
                  if update not in invalidUpdates:
                      invalidUpdates.append(update)
                  break
  for invalidUpdate in invalidUpdates:
      if invalidUpdate in updatesCopy:
          updatesCopy.remove(invalidUpdate)
  return updatesCopy
      

validUpdates = getValidUpdates(pageOrderingRules, updates)

def getMidPoint(arrays):
  midPoints = []
  for array in arrays:
      midPointIndex = len(array) // 2
      midPoints.append(array[midPointIndex])
  return midPoints

midPoints = getMidPoint(validUpdates)

print(sum(midPoints))

Part 2

This took me a while.

I understood what had to be done, but every time I reordered any pages that needed more than 1 set of pages to be swapped around, I got a got a bad answer. After a few tries and some logging, i found that I was swapping the same pages over and over again. I modified the swap function to get the index of the pages to be swapped and then this came together.

Part 2 Solution:

testPath = './testInput.txt'
inputPath = './input.txt'
chosenPath = inputPath

def parseInput(path):
  pageOrderingRules = []
  updates = []
  file = open(path, 'r')
  for line in file:
      if '|' in line:
          line = line.strip('
').split('|')
          line = list(map(int, line))
          pageOrderingRules.append(line)
      elif ',' in line:
          line = line.strip('
').split(',')
          line = list(map(int, line))
          updates.append(line)
  return pageOrderingRules, updates

pageOrderingRules, updates = parseInput(chosenPath)

def getInvalidUpdates(rules, updates):
  invalidUpdates = []
  def getPrecedingPages(page, rules):
      precedingPages = []
      for before, after in rules:
          if after == page:
              precedingPages.append(before)
      return precedingPages
  def getFollowingPages(page, rules):
      followingPages = []
      for before, after in rules:
          if before == page:
              followingPages.append(after)
      return followingPages
  for update in updates:
      for pageSeq, page in enumerate(update):
          precedingPages = getPrecedingPages(page, rules)
          followingPages = getFollowingPages(page, rules)
          for precedingPage in precedingPages:
              if precedingPage in update[pageSeq:] and update.index(precedingPage) > pageSeq:
                  if update not in invalidUpdates:
                      invalidUpdates.append(update)
                  break
          for followingPage in followingPages:
              if followingPage in update[:pageSeq] and update.index(followingPage) < pageSeq:
                  if update not in invalidUpdates:
                      invalidUpdates.append(update)
                  break
  return invalidUpdates
      

invalidUpdates = getInvalidUpdates(pageOrderingRules, updates)

def sortUpdates(rules, update):
  results = []
  def getApplicableRules(update, rules):
      matchedRules = []
      applicableRules = []
      for rule in rules:
          if rule[0] in update and rule[1] in update:
              matchedRules.append(rule)
      for rule in matchedRules:
          if update.index(rule[0]) > update.index(rule[1]):
              applicableRules.append(rule)
      return applicableRules

  def swapPages(page1, page2, update):
      page1Index = update.index(page1)
      page2Index = update.index(page2)
      update[page1Index], update[page2Index] = update[page2Index], update[page1Index]
      return update

  def reorder(update, rules):
      applicableRules = getApplicableRules(update, rules)
      if len(applicableRules) > 0:
          for rule in applicableRules:
              update = swapPages(rule[0], rule[1], update)
              return reorder(update, rules)
      return update
  
  reorderedUpdate = reorder(update, rules)
  rules = getApplicableRules(reorderedUpdate, rules)
  if len(rules) <= 0:
      results.append(reorderedUpdate)
  return results

results = []
for update in invalidUpdates:
  sortedUpdates = sortUpdates(pageOrderingRules, update)
  results.extend(sortedUpdates)

def getMidPoint(arrays):
  print(f'arrays: {arrays}')
  midPoints = []
  for array in arrays:
      print(f'looking at array: {array}')
      midPointIndex = len(array) // 2
      print(f' the midpoing is page: {array[midPointIndex]}')
      midPoints.append(array[midPointIndex])
  return midPoints


midponts = getMidPoint(results)
print(f' sum of midpoints is: {sum(midponts)}')