UNPKG

cube-notation-normalizer

Version:

Parse and "normalize" Rubik's Cube algorithm notations

117 lines (99 loc) 3.13 kB
var defaults = require('lodash/defaults') var Notation = require('./notation.js') var helper = require('./helper.js') var parse = Notation.parse function normalize (notation, options) { options = defaults(options, { separator: ' ', useModifiers: true, uniformCenterMoves: false, // false | 'rotation' | 'slice' invert: false }) var sequence = parse(notation) if (options.invert) { sequence = helper.invert(sequence) } if (options.uniformCenterMoves) { sequence = convertCenterMoves(sequence, options.uniformCenterMoves) } sequence = shrink(sequence) if (options.useModifiers) { return toHumanReadable(sequence, options.separator) } else { if (!options.separator) { return sequence } else { return sequence.split('').join(options.separator) } } } var MODIFIER = [undefined, '', '2', "'"] function toHumanReadable (sequence, separator) { return helper.chop(sequence) .map(move => move.charAt(0) + MODIFIER[move.length]) .join(separator) } var CENTER_MOVES_REPLACEMENT = { rotation: [ { pat: /r/g, rep: parse(" x L ") }, { pat: /l/g, rep: parse(" x' R ") }, { pat: /u/g, rep: parse(" y D ") }, { pat: /d/g, rep: parse(" y' U ") }, { pat: /f/g, rep: parse(" z B ") }, { pat: /b/g, rep: parse(" z' F ") }, { pat: /M/g, rep: parse(" x' R L' ") }, { pat: /E/g, rep: parse(" y' U D' ") }, { pat: /S/g, rep: parse(" z F' B ") } ], slice: [ { pat: /r/g, rep: parse(" R M' ") }, { pat: /l/g, rep: parse(" L M ") }, { pat: /u/g, rep: parse(" U E' ") }, { pat: /d/g, rep: parse(" D E ") }, { pat: /f/g, rep: parse(" F S ") }, { pat: /b/g, rep: parse(" B S' ") }, { pat: /x/g, rep: parse(" R M' L' ") }, { pat: /y/g, rep: parse(" U E' D' ") }, { pat: /z/g, rep: parse(" F S B' ") } ] } function convertCenterMoves (sequence, kind) { var table = CENTER_MOVES_REPLACEMENT[kind] for (var i = 0; i < table.length; i++) { sequence = sequence.replace(table[i].pat, table[i].rep) } return sequence } function shrink (sequence) { do { var oldLength = sequence.length sequence = sortAxisChunk(sequence) sequence = removeQuadruplets(sequence) var newLength = sequence.length } while (oldLength !== newLength) return sequence } function removeQuadruplets (sequence) { var regexp = /(.)\1{3}/g while (regexp.test(sequence)) { sequence = sequence.replace(regexp, '') } return sequence } function sortAxisChunk (sequence) { var chunked = sequence.match(/[RLMxrl]+|[UDEyud]+|[FBSzfb]+/g) if (chunked === null) return '' return chunked .map(chunk => chunk.split('').sort(compareFace).join('')) .join('') } var FACE_ORDER = { R: 0, L: 1, M: 2, x: 3, r: 4, l: 5, U: 0, D: 1, E: 2, y: 3, u: 4, d: 5, F: 0, B: 1, S: 2, z: 3, f: 4, b: 5 } function compareFace (a, b) { return FACE_ORDER[a] - FACE_ORDER[b] } module.exports = normalize module.exports.SyntaxError = Notation.SyntaxError