|  | 
|  | 1 | +import type { QuizData, Rules } from './fileReader.js' | 
|  | 2 | +import { uniformArrayElements, arrayMiddleIndex } from '@/utils/arrays.js' | 
|  | 3 | + | 
|  | 4 | +/** | 
|  | 5 | + * Checks if an "update" list is correct according to defined "rules" | 
|  | 6 | + * @param rules {Rules} Object containing parsed and formatted rules and updates data | 
|  | 7 | + * @param updateItems {number[]} "updates" item content | 
|  | 8 | + * @returns Flag indicating if the set of `updateItems` is correct | 
|  | 9 | + */ | 
|  | 10 | +export const isOrderedReport = (rules: Rules, updateItems: number[]): boolean => { | 
|  | 11 | +  let isOrdered = true | 
|  | 12 | + | 
|  | 13 | +  if (!uniformArrayElements(updateItems, 'number')) { | 
|  | 14 | +    throw new Error('Invalid updateItems item/s') | 
|  | 15 | +  } | 
|  | 16 | + | 
|  | 17 | +  for (let i = 0; i < updateItems.length - 1; i += 1) { | 
|  | 18 | +    const currentItem = updateItems[i] as number | 
|  | 19 | + | 
|  | 20 | +    // Current "update" item should have en entry in the "rules" object | 
|  | 21 | +    if (rules[currentItem] === undefined) { | 
|  | 22 | +      isOrdered = false | 
|  | 23 | +      break | 
|  | 24 | +    } | 
|  | 25 | + | 
|  | 26 | +    // Get the rest of items after the current item for comparison | 
|  | 27 | +    const afterItems = updateItems.filter((_, index) => index > i) | 
|  | 28 | + | 
|  | 29 | +    // Current item's "rule" should have the after-item entries | 
|  | 30 | +    if (!afterItems.every(item => rules[currentItem]?.includes(item))) { | 
|  | 31 | +      isOrdered = false | 
|  | 32 | +      break | 
|  | 33 | +    } | 
|  | 34 | + | 
|  | 35 | +    // Backtrack current item's inclusion in previous item maps | 
|  | 36 | +    if (i > 0) { | 
|  | 37 | +      for (let j = 0; j < i; j += 1) { | 
|  | 38 | +        const beforeItem = updateItems[j] as number | 
|  | 39 | + | 
|  | 40 | +        if (rules[beforeItem] === undefined) { | 
|  | 41 | +          isOrdered = false | 
|  | 42 | +          break | 
|  | 43 | +        } | 
|  | 44 | + | 
|  | 45 | +        if (!rules[beforeItem].includes(currentItem)) { | 
|  | 46 | +          isOrdered = false | 
|  | 47 | +          break | 
|  | 48 | +        } | 
|  | 49 | +      } | 
|  | 50 | +    } | 
|  | 51 | +  } | 
|  | 52 | + | 
|  | 53 | +  return isOrdered | 
|  | 54 | +} | 
|  | 55 | + | 
|  | 56 | +/** | 
|  | 57 | + * Counts the sum of middle page numbers from correctly-ordered "updates" | 
|  | 58 | + * @param data {QuizData} Object containing "rules" and "updates" input | 
|  | 59 | + * @param verbose {boolean} Flag to display processing log messages. Defaults to false. | 
|  | 60 | + * @returns {number} | 
|  | 61 | + */ | 
|  | 62 | +export const sumOfCorrectUpdates = (data: QuizData, verbose: boolean = false): number => { | 
|  | 63 | +  let sum = 0 | 
|  | 64 | + | 
|  | 65 | +  for (let i = 0; i < data.updates.length; i += 1) { | 
|  | 66 | +    const isOrdered = isOrderedReport(data.rules, data.updates[i] ?? []) | 
|  | 67 | + | 
|  | 68 | +    if (isOrdered) { | 
|  | 69 | +      if (verbose) { | 
|  | 70 | +        console.log('---correct', data.updates[i]) | 
|  | 71 | +      } | 
|  | 72 | + | 
|  | 73 | +      const mid = arrayMiddleIndex(data.updates[i] as number[]) | 
|  | 74 | +      const item = data.updates[i]?.[mid - 1] | 
|  | 75 | +      sum += item ?? 0 | 
|  | 76 | +    } | 
|  | 77 | +  } | 
|  | 78 | + | 
|  | 79 | +  return sum | 
|  | 80 | +} | 
0 commit comments