LoginSignup
6
5

More than 5 years have passed since last update.

常用域でO(1)のleftpad

Last updated at Posted at 2016-03-27

常用領域(追加するスペース/0の数が25個ぐらいだろうという想定)だとO(1)なleftpad実装です。チートです。0とスペース以外を埋めることはない、という割りきりで、それ以外が来たら拒否します。

常用領域外はO(n)ですが、O(n)表記は定数ぶぶんは省略してしまうので表記だけ見ても違いは分からないのですが、同じO(n)でも25個ずつ繋ぐので、最大で25倍速いです。node.js 5.7を利用してます。

4 8 16 32 64 128
leftpad 12 80 179 320 552 1100
lodash.startPad 60 219 237 257 275 303
チート版 12 15 13 24 31 49

数値は処理時間(mS)なので、短いほど良いという表です。

3/27追加: 要望があったのでlodash.startPad()との比較を追加

コードはPublic Domain(Unlicense)です。

leftpad.js
'use strict';

var padStart = require("lodash").padStart;

var spaces = [
    '',
    ' ',
    '  ',
    '   ',
    '    ',
    '     ',
    '      ',
    '       ',
    '        ',
    '         ',
    '          ',
    '           ',
    '            ',
    '             ',
    '              ',
    '               ',
    '                ',
    '                 ',
    '                  ',
    '                   ',
    '                    ',
    '                     ',
    '                      ',
    '                       ',
    '                        ',
    '                         '];

var zeros = [
    '',
    '0',
    '00',
    '000',
    '0000',
    '00000',
    '000000',
    '0000000',
    '00000000',
    '000000000',
    '0000000000',
    '00000000000',
    '000000000000',
    '0000000000000',
    '00000000000000',
    '000000000000000',
    '0000000000000000',
    '00000000000000000',
    '000000000000000000',
    '0000000000000000000',
    '00000000000000000000',
    '000000000000000000000',
    '0000000000000000000000',
    '00000000000000000000000',
    '000000000000000000000000',
    '0000000000000000000000000'];


// left-pad
function leftpad1(str, len, ch) {
  str = String(str);

  var i = -1;

  if (!ch && ch !== 0) ch = ' ';

  len = len - str.length;

  while (++i < len) {
    str = ch + str;
  }

  return str;
}

// チート版
function leftpad2(str, len, ch) {
  str = String(str);
  var chars;
  if (!ch && ch !== 0) chars = spaces;
  else if (ch === 0) chars = zeros;
  else if (ch === ' ') chars = spaces;
  else throw new Error("ch should be ' ' or 0");

  len = len - str.length;
  if (len < 1) {
    return str;
  } else if (len < 25) {
    return chars[len] + str;
  }
  var len2 = Math.floor(len / 25);
  var pad = chars[len % 25];
  for (var i=0; i<len2; i++) {
    pad += chars[25];
  }
  return pad + str
}

const len = parseInt(process.argv[2], 10);
const count = 1000000;

console.log("pad length", len);

console.log("leftpad1", leftpad1('aaaa', len, 0))
console.time('leftpad1');
for (let i = 0; i < count; i++) {
    leftpad1('aaaa', len, 0);
}
console.timeEnd('leftpad1');

console.log("padStart", padStart('aaaa', len, 0))
console.time('padStart');
for (let i = 0; i < count; i++) {
    padStart('aaaa', len, 0);
}
console.timeEnd('padStart');

console.log("leftpad2", leftpad2('aaaa', len, 0))
console.time('leftpad2');
for (let i = 0; i < count; i++) {
    leftpad2('aaaa', len, 0);
}
console.timeEnd('leftpad2');
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5