All files / day19 puzzle1.js

98.33% Statements 59/60
95.23% Branches 20/21
100% Functions 6/6
98.3% Lines 58/59

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 1201x   1x 557x 557x 557x         557x 557x     1x 3x 3x 556x 556x         3x     1x 206x 206x 206x 824x 824x   206x     1x 2x 2x 2x 761x 554x   207x     2x     1x             1326x 1326x 1326x 1845x 1845x 875x 157x 157x   718x 718x                   451x 451x 48x   403x                       1x 2x 2x 2x     2x   2x 205x 205x 205x 205x           205x 123x 123x     2x     1x  
const { readFile } = require('../helpers/file')
 
const parseWorkflow = (str) => {
  const workflowNameExtractor = new RegExp('(.+?)\\{', 'gm')
  const workflowName = workflowNameExtractor.exec(str)[1]
  const rules = str
    .replace(workflowName, '')
    .replace('{', '')
    .replace('}', '')
    .split(',')
  const fallback = rules.pop()
  return { name: workflowName, rules, fallback }
}
 
const buildWorkflowMap = (data) => {
  const workflowMap = new Map()
  for (const line of data) {
    const workflow = parseWorkflow(line)
    workflowMap.set(workflow.name, {
      rules: workflow.rules,
      fallback: workflow.fallback,
    })
  }
  return workflowMap
}
 
const parseParts = (str) => {
  let parts = str.replace('{', '').replace('}', '').split(',')
  const obj = {}
  for (const part of parts) {
    const keyValue = part.split('=')
    obj[keyValue[0]] = parseInt(keyValue[1])
  }
  return obj
}
 
const separateWorkflowParts = (fileContent) => {
  const dataWorkflow = []
  const dataParts = []
  for (const line of fileContent) {
    if (!line.startsWith('{') && line !== '') {
      dataWorkflow.push(line)
    } else {
      if (line !== '') dataParts.push(line)
    }
  }
  return [dataWorkflow, dataParts]
}
 
const computeIfPartAccepted = (
  workflowMap,
  rules,
  fallback,
  parsedPart,
  finalResult = null
) => {
  const { x, m, a, s } = parsedPart
  while (finalResult === null) {
    for (const rule of rules) {
      const [condition, goToStep] = rule.split(':')
      if (eval(condition)) {
        if (goToStep === 'A' || goToStep === 'R') {
          finalResult = goToStep
          return finalResult
        } else {
          rules = workflowMap.get(goToStep).rules
          return computeIfPartAccepted(
            workflowMap,
            workflowMap.get(goToStep).rules,
            workflowMap.get(goToStep).fallback,
            parsedPart,
            finalResult
          )
        }
      }
    }
    Eif (finalResult === null) {
      if (fallback === 'A' || fallback === 'R') {
        return fallback
      }
      return computeIfPartAccepted(
        workflowMap,
        workflowMap.get(fallback).rules,
        workflowMap.get(fallback).fallback,
        parsedPart,
        finalResult
      )
    }
  }
  return finalResult
}
 
const resolvePuzzle = (fileInput) => {
  const file = readFile(fileInput)
  const [dataWorkflow, dataParts] = separateWorkflowParts(file)
  let sum = 0
 
  // Build workflow map
  const workflowMap = buildWorkflowMap(dataWorkflow)
 
  for (const part of dataParts) {
    const parsedPart = parseParts(part)
    const rules = workflowMap.get('in').rules
    const fallback = workflowMap.get('in').fallback
    const finalResult = computeIfPartAccepted(
      workflowMap,
      rules,
      fallback,
      parsedPart
    )
    if (finalResult === 'A') {
      const { x, m, a, s } = parsedPart
      sum = sum + x + m + a + s
    }
  }
  return sum
}
 
module.exports = { parseWorkflow, parseParts, resolvePuzzle, buildWorkflowMap }