const { readdirSync } = require('fs');
const fs = require('fs');
const path = require('path');
const IGNORE_DIRS = ['.github', '.git', '.idea'];
const FOLDER_TO_LANG = {
javascript: 'JS',
typescript: 'TS',
csharp: 'C#',
c: 'C',
go: 'GO',
java: 'Java',
python: 'Python',
ruby: 'Ruby',
rust: 'Rust',
scala: 'Scala',
swift: 'Swift',
cpp: 'C++',
kotlin: 'Kotlin',
dart: 'Dart',
};
const PREPEND_PATH = process.argv[2] || './';
const TEMPLATE_PATH = process.argv[3] || './README_template.md';
const WRITE_PATH = process.argv[3] || './README.md';
const PROBLEM_SITE_DATA = JSON.parse(
fs.readFileSync('./.problemSiteData.json', 'utf8'),
);
function createProblemsObj(PROBLEM_SITE_DATA) {
let PROBLEMS_OBJ = {};
for (const { problem, pattern, link, code } of PROBLEM_SITE_DATA) {
if (!(pattern in PROBLEMS_OBJ)) PROBLEMS_OBJ[pattern] = [];
PROBLEMS_OBJ[pattern].push([
problem,
'https://leetcode.com/problems/' + link,
code.slice(0, 4),
]);
}
return PROBLEMS_OBJ;
}
const PROBLEMS_OBJ = createProblemsObj(PROBLEM_SITE_DATA);
const getDirectories = (source) =>
readdirSync(source, { withFileTypes: true })
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name);
function* walkSync(dir) {
const files = fs.readdirSync(dir, { withFileTypes: true });
for (const file of files) {
if (file.isDirectory()) {
yield* walkSync(path.join(dir, file.name));
} else {
yield path.join(dir, file.name);
}
}
}
function nestedFiles(dir) {
files = [];
for (const filePath of walkSync(dir)) {
files.push(filePath);
}
return files;
}
const directories = getDirectories(PREPEND_PATH).filter(
(dir) => !IGNORE_DIRS.includes(dir),
);
const nestedFilesInDir = directories.reduce((acc, dir) => {
acc[dir] = nestedFiles(dir);
return acc;
}, {});
const tableHeader =
[
'Problem',
...directories.map((folder) => FOLDER_TO_LANG[folder] || folder),
]
.map((el) => `<sub>${el}</sub>`)
.join(' | ') + '\n';
const tableSep =
Array.from({ length: tableHeader.split('|').length })
.map((el) => '----')
.join(' | ') + '\n';
let fullOutput = '';
for (const problemCategory in PROBLEMS_OBJ) {
fullOutput += `### ${problemCategory}\n\n`;
fullOutput += tableHeader;
fullOutput += tableSep;
for (const [problemName, problemUrl, problemNumber] of PROBLEMS_OBJ[
problemCategory
]) {
let problemRow = [
`<sub>[${problemNumber} - ${problemName}](${problemUrl})</sub>`,
];
for (const dir of directories) {
let filePath = nestedFilesInDir[dir].find((file) =>
file.match(/[\w-]+\..+/)?.[0]?.startsWith(problemNumber),
);
if (filePath) {
problemRow.push(
`<sub><div align='center'>[✔️](${encodeURIComponent(
filePath,
)})</div></sub>`,
);
} else {
problemRow.push("<sub><div align='center'>❌</div></sub>");
}
}
fullOutput += problemRow.join(' | ') + '\n';
}
fullOutput += '\n';
}
const template = fs.readFileSync(TEMPLATE_PATH, { encoding: 'utf8' });
const toWrite = template.replaceAll('<completion-tables />', fullOutput);
console.log(toWrite);
fs.writeFileSync(WRITE_PATH, toWrite, {
encoding: 'utf8',
});