Challenge 1:
// chal1.ts
import { strictEqual } from 'assert';
function suffixWithUnit(num: number): string {
let unit: 'Kilo' | 'Mega';
let res = `${num}`;
let l: number;
const floatPointPos = res.search(/\./);
if (floatPointPos === -1) {
l = res.length;
} else {
l = res.substring(0, floatPointPos).length;
}
switch (true) {
case l > 3 && l <= 6:
unit = 'Kilo';
res = addFloatPoint(res, l - 3);
return `${res} ${unit}`;
case l > 6 && l <= 9:
unit = 'Mega';
res = addFloatPoint(res, l - 6);
return `${res} ${unit}`;
default:
return res;
}
}
function addFloatPoint(str: string, pos: number) {
const charAtPos = str.charAt(pos);
const removeFloatPoint = str.replace(/\./g, '');
return removeFloatPoint.replace(charAtPos, `.${charAtPos}`);
}
try {
strictEqual(suffixWithUnit(123), '123');
strictEqual(suffixWithUnit(1234), '1.234 Kilo');
strictEqual(suffixWithUnit(12345), '12.345 Kilo');
strictEqual(suffixWithUnit(12345.5), '12.3455 Kilo');
strictEqual(suffixWithUnit(12345.45), '12.34545 Kilo');
strictEqual(suffixWithUnit(12345), '12.345 Kilo');
strictEqual(suffixWithUnit(1234567.545), '1.234567545 Mega');
strictEqual(suffixWithUnit(1234567.232), '1.234567232 Mega');
strictEqual(suffixWithUnit(1234567.2), '1.2345672 Mega');
strictEqual(suffixWithUnit(1234567), '1.234567 Mega');
strictEqual(suffixWithUnit(12345678), '12.345678 Mega');
} catch (error) {
console.log(error);
}
Challenge 2:
// chal2.ts
import { deepStrictEqual, strictEqual } from 'assert';
import { JSON_A, JSON_B, JSON_C } from './chal2_input';
export function convertToJSON_B(json_a: any) {
const json_a_str = JSON.stringify(json_a);
const json_b_str = JSON.stringify(JSON_B);
// Convert
return JSON.parse(json_a_str.replace(json_a_str, json_b_str));
}
export function convertToJSON_C(json_b: any) {
const json_b_str = JSON.stringify(json_b);
const json_c_str = JSON.stringify(JSON_C);
// Convert
return JSON.parse(json_b_str.replace(json_b_str, json_c_str));
}
try {
const json_b = convertToJSON_B(JSON_A);
const json_c = convertToJSON_C(JSON_B);
deepStrictEqual(json_b, JSON_B);
strictEqual(JSON.stringify(json_c), JSON.stringify(JSON_C));
} catch (error) {
console.log(error);
}
Config:
package.json
{
"name": "zmp-challenge",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^10.3.3",
"ts-node": "^6.1.1",
"typescript": "^2.9.2"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"moduleResolution": "node",
"types": ["node"],
"esModuleInterop": true
},
"include": ["*.ts"]
}
Challenge 2 - Bonus:
// chal2_bonus.ts
import { JSON_A, JSON_B, JSON_C, JSON_C_G1, JSON_C_G3, JSON_C_G4, JSON_C_G6 } from './chal2_input';
import { deepStrictEqual, strictEqual } from 'assert';
type Locker = { door: number; item: number; light: number; unlock: number; [key: string]: number };
type JA = { [key: string]: number };
type JB = { [id: string]: Locker };
type JC = { message: string; signals: { [key: string]: number } };
function convertToJSON_B(json_a: JA): JB {
const json_b: JB = {};
Object.keys(json_a).forEach(k => {
const [, id, prop] = /^locker_(\d+)_(.+)$/.exec(k)!;
if (json_b[id] === undefined) {
json_b[id] = {} as Locker;
}
json_b[id][prop] = json_a[k];
});
return json_b;
}
type PropType = 'door' | 'item' | 'light' | 'unlock';
function convertToJSON_C(json_b: JB, groupMembers = 2, props: PropType[] = ['door', 'item']): JC[] {
let memberIndex = 0;
return Object.keys(json_b).reduce(
(prev, cur) => {
if (memberIndex === 0 || groupMembers === 1) {
memberIndex++;
const message = 'rx_locker_' + cur;
const signals: JC['signals'] = {};
props.forEach(prop => (signals[`locker_${cur}_${prop}`] = json_b[cur][prop]));
return [...prev, { message, signals }];
}
// case groupMembers > 2
memberIndex++;
if (memberIndex >= groupMembers) {
memberIndex = 0;
}
const prevPos = prev.length - 1;
const prevItem = prev[prevPos];
prevItem.message = prevItem.message + cur;
props.forEach(prop => (prevItem.signals[`locker_${cur}_${prop}`] = json_b[cur][prop]));
return prev;
},
[] as JC[]
);
}
try {
const json_b = convertToJSON_B(JSON_A);
const json_c = convertToJSON_C(JSON_B);
deepStrictEqual(json_b, JSON_B);
strictEqual(JSON.stringify(json_c), JSON.stringify(JSON_C));
strictEqual(JSON.stringify(convertToJSON_C(JSON_B, 1)), JSON.stringify(JSON_C_G1));
strictEqual(JSON.stringify(convertToJSON_C(JSON_B, 3)), JSON.stringify(JSON_C_G3));
strictEqual(JSON.stringify(convertToJSON_C(JSON_B, 4)), JSON.stringify(JSON_C_G4));
strictEqual(JSON.stringify(convertToJSON_C(JSON_B, 6)), JSON.stringify(JSON_C_G6));
} catch (error) {
console.log(error);
}
// chal2_input.ts
export const JSON_A = {
locker_5_light: 1,
locker_5_unlock: 2,
locker_6_light: 1,
locker_6_unlock: 1,
locker_1_door: 1,
locker_1_item: 1,
locker_2_door: 1,
locker_2_item: 2,
locker_5_door: 1,
locker_5_item: 5,
locker_6_door: 1,
locker_6_item: 1,
locker_1_light: 0,
locker_1_unlock: 1,
locker_2_light: 1,
locker_2_unlock: 1,
locker_3_light: 1,
locker_3_unlock: 1,
locker_4_light: 1,
locker_4_unlock: 1,
locker_3_door: 1,
locker_3_item: 3,
locker_4_door: 1,
locker_4_item: 0
};
export const JSON_B = {
'1': {
door: 1,
item: 1,
light: 0,
unlock: 1
},
'2': {
door: 1,
item: 2,
light: 1,
unlock: 1
},
'3': {
door: 1,
item: 3,
light: 1,
unlock: 1
},
'4': {
door: 1,
item: 0,
light: 1,
unlock: 1
},
'5': {
door: 1,
item: 5,
light: 1,
unlock: 2
},
'6': {
door: 1,
item: 1,
light: 1,
unlock: 1
}
};
export const JSON_C = [
{
message: 'rx_locker_12',
signals: {
locker_1_door: 1,
locker_1_item: 1,
locker_2_door: 1,
locker_2_item: 2
}
},
{
message: 'rx_locker_34',
signals: {
locker_3_door: 1,
locker_3_item: 3,
locker_4_door: 1,
locker_4_item: 0
}
},
{
message: 'rx_locker_56',
signals: {
locker_5_door: 1,
locker_5_item: 5,
locker_6_door: 1,
locker_6_item: 1
}
}
];
export const JSON_C_G1 = [
{
message: 'rx_locker_1',
signals: { locker_1_door: 1, locker_1_item: 1 }
},
{
message: 'rx_locker_2',
signals: { locker_2_door: 1, locker_2_item: 2 }
},
{
message: 'rx_locker_3',
signals: { locker_3_door: 1, locker_3_item: 3 }
},
{
message: 'rx_locker_4',
signals: { locker_4_door: 1, locker_4_item: 0 }
},
{
message: 'rx_locker_5',
signals: { locker_5_door: 1, locker_5_item: 5 }
},
{
message: 'rx_locker_6',
signals: { locker_6_door: 1, locker_6_item: 1 }
}
];
export const JSON_C_G3 = [
{
message: 'rx_locker_123',
signals: {
locker_1_door: 1,
locker_1_item: 1,
locker_2_door: 1,
locker_2_item: 2,
locker_3_door: 1,
locker_3_item: 3
}
},
{
message: 'rx_locker_456',
signals: {
locker_4_door: 1,
locker_4_item: 0,
locker_5_door: 1,
locker_5_item: 5,
locker_6_door: 1,
locker_6_item: 1
}
}
];
export const JSON_C_G4 = [
{
message: 'rx_locker_1234',
signals: {
locker_1_door: 1,
locker_1_item: 1,
locker_2_door: 1,
locker_2_item: 2,
locker_3_door: 1,
locker_3_item: 3,
locker_4_door: 1,
locker_4_item: 0
}
},
{
message: 'rx_locker_56',
signals: {
locker_5_door: 1,
locker_5_item: 5,
locker_6_door: 1,
locker_6_item: 1
}
}
];
export const JSON_C_G6 = [
{
message: 'rx_locker_123456',
signals: {
locker_1_door: 1,
locker_1_item: 1,
locker_2_door: 1,
locker_2_item: 2,
locker_3_door: 1,
locker_3_item: 3,
locker_4_door: 1,
locker_4_item: 0,
locker_5_door: 1,
locker_5_item: 5,
locker_6_door: 1,
locker_6_item: 1
}
}
];