栅栏加密方法·

栅栏加密

/**
 * @typedef {string[]} Rail
 * @typedef {Rail[]} Fence
 * @typedef {number} Direction
 */

/**
 * @constant DIRECTIONS
 * @type {object}
 * @property {Direction} UP
 * @property {Direction} DOWN
 */
const DIRECTIONS = { UP: -1, DOWN: 1 };

/**
 * 构建具有特定行数的栅栏。
 *
 * @param {number} rowsNum - 栅栏中的行数
 * @returns {Fence} - 返回一个二维数组,表示栅栏
 */
const buildFence = (rowsNum) => Array(rowsNum)
  .fill(null)
  .map(() => []);

/**
 * 获取在穿越栅栏时下一个移动方向(基于当前方向)。
 *
 * @param {object} params
 * @param {number} params.railCount - 栅栏的行数
 * @param {number} params.currentRail - 当前正在访问的行
 * @param {Direction} params.direction - 当前方向
 * @returns {Direction} - 下一个要采取的方向
 */
const getNextDirection = ({ railCount, currentRail, direction }) => {
  switch (currentRail) {
    case 0:
      // 如果在栅栏顶部,向下移动。
      return DIRECTIONS.DOWN;
    case railCount - 1:
      // 如果在栅栏底部,向上移动。
      return DIRECTIONS.UP;
    default:
      // 如果在栅栏中间,继续使用相同的方向。
      return direction;
  }
};

/**
 * @param {number} targetRailIndex - 目标行的索引
 * @param {string} letter - 要添加到行的字符
 * @returns {Function} - 返回一个函数,用于将字符添加到行
 */
const addCharToRail = (targetRailIndex, letter) => {
  /**
   * 如果匹配目标索引,则将字符添加到行的函数。
   *
   * @param {Rail} rail - 当前行
   * @param {number} currentRail - 当前行的索引
   * @returns {Rail} - 返回更新后的行
   */
  function onEachRail(rail, currentRail) {
    return currentRail === targetRailIndex
      ? [...rail, letter]
      : rail;
  }
  return onEachRail;
};

/**
 * 将字符挂在栅栏上。
 *
 * @param {object} params
 * @param {Fence} params.fence - 栅栏
 * @param {number} params.currentRail - 当前行
 * @param {Direction} params.direction - 移动方向
 * @param {string[]} params.chars - 要挂在栅栏上的字符数组
 * @returns {Fence} - 返回更新后的栅栏
 */
const fillEncodeFence = ({
  fence,
  currentRail,
  direction,
  chars,
}) => {
  if (chars.length === 0) {
    // 所有字符都已经挂在栅栏上。
    return fence;
  }

  const railCount = fence.length;

  // 获取下一个要挂在栅栏上的字符。
  const [letter, ...nextChars] = chars;
  const nextDirection = getNextDirection({
    railCount,
    currentRail,
    direction,
  });

  return fillEncodeFence({
    fence: fence.map(addCharToRail(currentRail, letter)),
    currentRail: currentRail + nextDirection,
    direction: nextDirection,
    chars: nextChars,
  });
};

/**
 * @param {object} params
 * @param {number} params.strLen - 字符串长度
 * @param {string[]} params.chars - 字符数组
 * @param {Fence} params.fence - 栅栏
 * @param {number} params.targetRail - 目标行索引
 * @param {Direction} params.direction - 移动方向
 * @param {number[]} params.coords - 坐标
 * @returns {Fence} - 返回更新后的栅栏
 */
const fillDecodeFence = (params) => {
  const {
    strLen, chars, fence, targetRail, direction, coords,
  } = params;

  const railCount = fence.length;

  if (chars.length === 0) {
    return fence;
  }

  const [currentRail, currentColumn] = coords;
  const shouldGoNextRail = currentColumn === strLen - 1;
  const nextDirection = shouldGoNextRail
    ? DIRECTIONS.DOWN
    : getNextDirection(
      { railCount, currentRail, direction },
    );
  const nextRail = shouldGoNextRail ? targetRail + 1 : targetRail;
  const nextCoords = [
    shouldGoNextRail ? 0 : currentRail + nextDirection,
    shouldGoNextRail ? 0 : currentColumn + 1,
  ];

  const shouldAddChar = currentRail === targetRail;
  const [currentChar, ...remainderChars] = chars;
  const nextString = shouldAddChar ? remainderChars : chars;
  const nextFence = shouldAddChar ? fence.map(addCharToRail(currentRail, currentChar)) : fence;

  return fillDecodeFence({
    strLen,
    chars: nextString,
    fence: nextFence,
    targetRail: nextRail,
    direction: nextDirection,
    coords: nextCoords,
  });
};

/**
 * @param {object} params
 * @param {number} params.strLen - 字符串长度
 * @param {Fence} params.fence - 栅栏
 * @param {number} params.currentRail - 当前行
 * @param {Direction} params.direction - 移动方向
 * @param {number[]} params.code - 解码后的字符数组
 * @returns {string} - 返回解码后的字符串
 */
const decodeFence = (params) => {
  const {
    strLen,
    fence,
    currentRail,
    direction,
    code,
  } = params;

  if (code.length === strLen) {
    return code.join('');
  }

  const railCount = fence.length;

  const [currentChar, ...nextRail] = fence[currentRail];
  const nextDirection = getNextDirection(
    { railCount, currentRail, direction },
  );

  return decodeFence({
    railCount,
    strLen,
    currentRail: currentRail + nextDirection,
    direction: nextDirection,
    code: [...code, currentChar],
    fence: fence.map((rail, idx) => (idx === currentRail ? nextRail : rail)),
  });
};

/**
 * 使用铁栅栏密码对消息进行编码。
 *
 * @param {string} string - 要编码的字符串
 * @param {number} railCount - 栅栏的行数
 * @returns {string} - 编码后的字符串
 */
const encodeRailFenceCipher = (string, railCount) => {
  const fence = buildFence(railCount);

  const filledFence = fillEncodeFence({
    fence,
    currentRail: 0,
    direction: DIRECTIONS.DOWN,
    chars: string.split(''),
  });

  return filledFence.flat().join('');
};

/**
 * 使用铁栅栏密码对消息进行解码。
 *
 * @param {string} string - 编码后的字符串
 * @param {number} railCount - 栅栏的行数
 * @returns {string} - 解码后的字符串
 */
const decodeRailFenceCipher = (string, railCount) => {
  const strLen = string.length;
  const emptyFence = buildFence(railCount);
  const filledFence = fillDecodeFence({
    strLen,
    chars: string.split(''),
    fence: emptyFence,
    targetRail: 0,
    direction: DIRECTIONS.DOWN,
    coords: [0, 0],
  });

  return decodeFence({
    strLen,
    fence: filledFence,
    currentRail: 0,
    direction: DIRECTIONS.DOWN,
    code: [],
  });
};

const originalMessage = "123456789"; // 要编码的消息
const railCount = 3; // 设置栅栏的行数

const encodedMessage = encodeRailFenceCipher(originalMessage, railCount);

console.log("编码后的消息: " + encodedMessage);

const decodedMessage = decodeRailFenceCipher(encodedMessage, railCount);

console.log("解码后的消息: " + decodedMessage);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值