<commit_before>const fs = require('fs')

let input = fs.readFileSync('./input2.txt', 'utf8').trim()
let instructions = input.split('\n').map(x => x.trim().toUpperCase().split(''))

function solve(keypad, instructions, start) {
    let directions = {'U': [0, -1], 'L': [-1, 0], 'D': [0, 1], 'R': [1, 0]}
    let valid = ([x, y]) => y in keypad && keypad[y][x] != null

    if (!valid(start)) return ''

    let [passcode, ] = instructions.reduce(([passcode, position], chunk) => {
        [x, y] = chunk.reduce((position, uldr) => {
            let newPosition = directions[uldr].map((x, i) => position[i] + x)
            return valid(newPosition) ? newPosition : position
        }, position)

        return [passcode + keypad[y][x], [x, y]]
    }, ['', start])

    return passcode
}

let normalKeypad = [
    ['1', '2', '3'],
    ['4', '5', '6'],
    ['7', '8', '9']
]

console.log('Part 1:\t', solve(normalKeypad, instructions, [1, 1]))

let weirdKeypad = [
    [null, null, '1', null, null],
    [null,  '2', '3',  '4', null],
    [ '5',  '6', '7',  '8',  '9'],
    [null,  'A', 'B',  'C', null],
    [null, null, 'D', null, null]
]

console.log('Part 2:\t', solve(weirdKeypad, instructions, [0, 2]))<commit_msg>Rewrite using composition of small functions<commit_after>const fs = require('fs')

let input = fs.readFileSync('./input2.txt', 'utf8').trim()
let instructions = input.split('\n').map(x => x.trim().toUpperCase().split(''))

const directions = {'U': [0, -1], 'L': [-1, 0], 'D': [0, 1], 'R': [1, 0]}

let valid = (kp, [x, y]) => y in kp && kp[y][x] != null
let add = (a, b) => a.map((x, i) => x + b[i])
let goDirection = (kp, p, uldr) => valid(kp, add(p, directions[uldr])) ? add(p, directions[uldr]) : p
let followChunk = (kp, s, chunk) => chunk.reduce((...pd) => goDirection(kp, ...pd), s)
let followInstr = (kp, s, instr) => instr.reduce((acc, chunk) => [...acc, followChunk(kp, acc.slice(-1)[0], chunk)], [s])
let getCode = (kp, positions) => positions.map(([x, y]) => kp[y][x]).join('')
let solve = (kp, s, instr) => getCode(kp, followInstr(kp, s, instr).slice(1))

let normalKeypad = [
    ['1', '2', '3'],
    ['4', '5', '6'],
    ['7', '8', '9']
]

console.log('Part 1:\t', solve(normalKeypad, [1, 1], instructions))

let weirdKeypad = [
    [null, null, '1', null, null],
    [null,  '2', '3',  '4', null],
    [ '5',  '6', '7',  '8',  '9'],
    [null,  'A', 'B',  'C', null],
    [null, null, 'D', null, null]
]

console.log('Part 2:\t', solve(weirdKeypad, [0, 2], instructions))
{'fraction_non_alphanumeric': 0.2650698602794411, 'fraction_numerical': 0.028343313373253493, 'mean_word_length': 3.5153153153153154, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2414755', 'n_tokens_mistral': 1022, 'n_tokens_neox': 975, 'n_words': 264}