1. Скорость
Что касается скорости алгоритма, есть следующие соображения:
- Примерно половина итераций цикла не приведет к результату. Это можно улучшить;
- Существует шаблон, который повторяется каждые 15 итераций, потому что наименьшее общее кратное 3 и 5 равно 15.
Таким образом, вы можете жестко закодировать этот шаблон в свой код и выполнить вывод, соответствующий диапазону от 1 до 15, а затем повторить:
function counterPattern() {
for (let i = 0; i < 90; i += 15) {
console.log("a"); // 3 + i
console.log("b"); // 5 + i
console.log("a"); // 6 + i
console.log("a"); // 9 + i
console.log("b"); // 10 + i
console.log("a"); // 12 + i
console.log("c"); // 15 + i
}
// The remainder: values between 90 and 100:
console.log("a"); // 93
console.log("b"); // 95
console.log("a"); // 96
console.log("a"); // 99
console.log("b"); // 100
}
counterPattern();
2. Тестирование
Чтобы сделать этот код пригодным для тестирования, у вас есть несколько вариантов. Использование массива, как и вы, является одним из них. Вы также можете рассмотреть возможность превращения функции в генератор, а затем использовать yield
для вывода значений.
Но есть также решение, при котором вам не нужно трогать код функции: либо используйте дразнить или шпионить, чтобы подключиться к console.log
. Библиотеки модульного тестирования обычно предлагают такие функции.
Во-вторых, нет лучшей ссылки для проверки, чем исходная функция. Таким образом, вы можете сначала запустить исходную функцию для получения ожидаемого результата, а затем запустить улучшенную реализацию. Наконец, два выхода должны быть сравнены.
Вот как будет работать насмешка без использования внешней библиотеки:
function test() { // Wrapper to keep the mocking local
function orig_counterPattern() { // The reference implementation
for (let i = 1; i <= 100; i++) {
if (i % 3 === 0 && i % 5 === 0) {
console.log("c");
} else if (i % 3 === 0) {
console.log("a");
} else if (i % 5 === 0) {
console.log("b");
}
}
}
function counterPattern() { // Our own implementation
for (let i = 0; i < 90; i += 15) {
console.log("a"); // 3 + i
console.log("b"); // 5 + i
console.log("a"); // 6 + i
console.log("a"); // 9 + i
console.log("b"); // 10 + i
console.log("a"); // 12 + i
console.log("c"); // 15 + i
}
// The remainder: values between 90 and 100:
console.log("a"); // 93
console.log("b"); // 95
console.log("a"); // 96
console.log("a"); // 99
console.log("b"); // 100
}
// Mock console object:
let console = {
log: (value) => output.push(value)
};
// Collect the expected output
let output = [];
orig_counterPattern();
let reference = [...output];
// Run our own implementation
output = [];
counterPattern();
let result = [...output];
// Stop mocking the console object
console = globalThis.console;
// Compare
console.assert(output.length === reference.length, "incorrect number of outputs");
console.assert(reference.every((ref, i) => ref === result[i], "mismatch"));
}
test();
console.log("Test completed.");
Более короткий код
Во-первых, вы, конечно, можете жестко закодировать вывод полностью, даже избегая цикла. Но это противоречило бы принципу, что мы не должны повторяться (СУХОЙ).
Вот вариант, который немного более СУХОЙ:
function counterPattern() {
let pattern = "abaabac".repeat(105/15).slice(0, -2);
for (let c of pattern) console.log(c);
}
counterPattern();
person
trincot
schedule
14.08.2020