Mego

// 注: 所有题目均可以使用任意 ES 版本中的 API
/**
 * Q1: 实现一个非原生类(不考虑数组, Map, Set, Date 等内部类)的浅拷贝函数
 *
 * 此函数接收一个非原生类对象(可能有自定义的原型链), 返回
 * 一个此对象的浅拷贝.
 */
function shallowCopy(obj) {
  // 1.使用 Object.assign 实行浅拷贝
  return Object.assign({}, obj)
  
  // 2.使用扩张运算符
  // return {...obj}
  
  // 3.使用 Javascript 方法
  // let shallowObj = {}
  
  // for(let item in obj){
  //   if(obj.hasOwnProperty(item)){
  //      shallowObj[item] = obj[item]
  //   }
  // }
  
  // return shallowObj
}
/**
 * Q2: 实现一个加权随机函数
 *
 * 此函数接收一个整数数组 input, 此数组:
 *  1. 元素个数 N < 10000
 *  2. 元素的值大于 0 且小于 100
 *
 * 返回一个随机函数, 此随机函数:
 *  1. 返回 [0, N - 1] 之间的一个随机整数
 *  2. 每个整数 i 被返回的概率为:
 *     数组 input 的第 i 个元素的值 / 数组 arr 的所有元素之和
 *
 * 例: 给定一个数组 input, 值为 [4, 2, 1, 3],
 *    调用 createWeightedRandom(input), 应当
 *    返回一个函数, 此函数返回一个 0 - 3 之间的一个
 *    随机整数, 相应的概率分别为:
 *    4/10, 2/10, 1/10, 3/10.
 *
 * 分别按以下两种要求实现该函数:
 * 1. 空间复杂度不限, 返回的随机函数时间复杂度 O(1)
 * 2. 空间复杂度 O(N), 返回的随机函数时间复杂度 O(logN)
 */
// Q2.1: 空间复杂度不限, 返回的随机函数时间复杂度 O(1)
function createWeightedRandom_O1(input) {
  const len = input.length
  
  if(len === 0) return null
  // show me the code, please delete the following line.
  throw new Error('not implemented');
}
// Q2.2: 空间复杂度 O(N), 返回的随机函数时间复杂度 O(logN)
function createWeightedRandom_OlogN(input) {
  // show me the code, please delete the following line.
  throw new Error('not implemented');
}

function getSum(input){
  return input.reduce((pre, cur) => {
    return pre + cur
  })
}


function getRatio(input){
  let map = new Map(), sum = getSum(input)
  
  for(let el of input) {
    map.set()
  }
}

function random(input){
  let random = Math.floor(Math.random() * 100)
  
  return random
}



console.log('random',random([1,2,3,5]))

/**
 * Q3: 实现一个异步任务执行器 AsyncWorker
 *
 * 此 AsyncWorker: 最多只能同时执行 capacity
 * 个异步任务. 若正在执行的任务数达到 capacity,
 * 则新加入的任务需要等待其中一个正在执行的任务完
 * 成后才能被执行.
 */
class AsyncWorker {
  constructor(capacity) {
    this.capacity = capacity;
  }
  exec(task) {
    // show me the code, please delete the following line.
    throw new Error('not implemented');
  }
}
/* -------- 下面是测试代码 --------- */
function assert(value, message) {
  if (value !== true) {
    throw new Error(message);
  }
}
// TEST Q1
function testShallowCopy() {
  class UserModel {
    constructor(firstName, lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
    }
    fullName() {
      return this.firstName + ' ' + this.lastName;
    }
  }
  const user = new UserModel('Hello', 'World');
  const user2 = shallowCopy(user);
  user2.firstName = 'Hello 2';
  user2.lastName = 'World 2';
  assert(user2 instanceof UserModel, 'should be instance');
  assert(user.fullName() === 'Hello World', 'should keep original fields');
  assert(user2.fullName() === 'Hello 2 World 2', 'should returns new value');
}
// TEST Q2.1
function testCreateWeightedRandom_O1() {
  const input = [4, 2, 1, 3];
  const sampling = createWeightedRandom_O1(input);
  const count = [0, 0, 0, 0];
  for (let i = 0; i < 10000; i++) {
    count[sampling()]++;
  }
  const rates = count.map((i) => Math.round(i / 1000));
  assert(JSON.stringify(rates) === '[4,2,1,3]', `${rates} is not same to ${input}`);
}
// TEST Q2.2
function testCreateWeightedRandom_OlogN() {
  const input = [4, 2, 1, 3];
  const sampling = createWeightedRandom_OlogN(input);
  const count = [0, 0, 0, 0];
  for (let i = 0; i < 10000; i++) {
    count[sampling()]++;
  }
  const rates = count.map((i) => Math.round(i / 1000));
  assert(JSON.stringify(rates) === '[4,2,1,3]', `${rates} is not same to ${input}`);
}
// TEST Q3
async function testAsyncWorker() {
  const start = Date.now();
  const createTask = (timeout, error) => {
    return () => new Promise((resolve, reject) => {
      setTimeout(() => {
        if (error) {
          reject(error);
        }
        else {
          resolve(timeout);
        }
      }, timeout);
    });
  };
  const worker = new AsyncWorker(2);
  const tasks = [
    { status: 'fulfilled', value: 100, idealCost: 100, task: worker.exec(createTask(100)) },
    { status: 'fulfilled', value: 201, idealCost: 200, task: worker.exec(createTask(201)) },
    { status: 'rejected', reason: 'REJECTED', idealCost: 300, task: worker.exec(createTask(202, 'REJECTED')) },
    { status: 'fulfilled', value: 203, idealCost: 400, task: worker.exec(createTask(203)) },
    { status: 'fulfilled', value: 300, idealCost: 600, task: worker.exec(createTask(300)) },
  ];
  // show me bug does not support for of tasks.entries()
  for (let index = 0; index < tasks.length; index++) {
    const t = tasks[index];
    let result;
    try {
      const value = await t.task;
      result = { status: 'fulfilled', value };
    }
    catch (e) {
      result = { status: 'rejected', reason: e };
    }
    const realCost = Date.now() - start;
    const idealCost = (realCost - (realCost % 100)) | 0;
    if (idealCost !== t.idealCost) {
      throw new Error(`unexpected time cost: ${idealCost}, expected is ${t.idealCost} for ${index}`);
    }
    if (result.status !== t.status) {
      throw new Error(`unexpected status ${result.status} for ${index}`);
    }
    if (t.status === 'fulfilled' && result.status === 'fulfilled' && result.value !== t.value) {
      throw new Error(`unexpected fulfilled value ${result.value}, expected is ${t.value} for ${index}`);
    }
    if (t.status === 'rejected' && result.status === 'rejected' && result.reason !== t.reason) {
      throw new Error(`unexpected rejected reason ${result.reason}, expected is ${t.reason} for ${index}`);
    }
  }
}
async function main() {
  try {
    console.log('Testing Q1...');
    await testShallowCopy();
    console.log('PASSED!');
  }
  catch (e) {
    console.log(e.stack || e);
  }
  try {
    console.log('Testing Q2.1...');
    await testCreateWeightedRandom_O1();
    console.log('PASSED!');
  }
  catch (e) {
    console.log(e.stack || e);
  }
  try {
    console.log('Testing Q2.2...');
    await testCreateWeightedRandom_OlogN();
    console.log('PASSED!');
  }
  catch (e) {
    console.log(e.stack || e);
  }
  try {
    console.log('Testing Q3...');
    await testAsyncWorker();
    console.log('PASSED!');
  }
  catch (e) {
    console.log(e.stack || e);
  }
}
main();
上次更新:
贡献者: Joe