Счастливые билеты любой длины на JavaScript

В предыдущем уроке мы с вами решили задачу на нахождение всех счастливых чисел. Давайте теперь обобщим наш код так, чтобы в билете было не 6 цифр, а любое заданное количество.

Теперь уже я не буду писать весь код за вас, а буду говорить, какие функции нам будут нужны, как мы ими будем пользоваться, а сам код функций вы напишите самостоятельно.

Итак, приступим.

Функция isLucky

В предыдущем уроке у нас была функция isLucky, которая параметром принимала число, нормализовала его с помощью вспомогательной функции normalizeNum, находила суммы цифр и проверяла равенства сумм:

function isLucky(num) { let str = normalizeNum(num); let sum1 = Number(str[0]) + Number(str[1]) + Number(str[2]); let sum2 = Number(str[3]) + Number(str[4]) + Number(str[5]); return sum1 == sum2; }

Сейчас я предлагаю вынести нормализацию за функцию. Пусть isLucky параметром принимает уже нормализованное число (то есть строку, дополненную при необходимости нулями спереди).

Давайте считать, что в функцию всегда будет передаваться число с любым четным количеством цифр. Наша функция должна взять первую половину цифр, найти их сумму, затем взять вторую половину цифр, найти их сумму, а затем проверить равенство сумм.

Вот примеры того, как мы можем пользоваться нашей функцией:

console.log(isLucky('1203')); console.log(isLucky('012003')); console.log(isLucky('123006')); console.log(isLucky('33'));

Реализуйте описанную функцию. Потестируйте ее работу.

Функция normalizeNum

Давайте теперь доработаем функцию normalizeNum, чтобы она работала с числами произвольной длины, а не только с 6-ть цифрами.

Напомню код этой функции, созданный нами в предыдущем уроке:

function normalizeNum(num) { let str = String(num); if (str.length == 5) { str = '0' + str; } if (str.length == 4) { str = '00' + str; } return str; }

Как вы видите, функция просто проверяла длину строки и, если длина была 5, то добавляла спереди один ноль, а если длина была 6 - то два нуля.

Давайте теперь будем передавать вторым параметром количество цифр, которое должно быть в билете. К примеру, если мы передадим 4, то в билете должно быть 4 цифры и, если их меньше, то наше число будет спереди дополнятся нулями так, чтобы цифр стало 4.

Вот примеры того, как наша функция будет дополнять до 4-х цифр:

console.log(normalizeNum(1, 4)); // выведет '0001' console.log(normalizeNum(12, 4)); // выведет '0012' console.log(normalizeNum(123, 4)); // выведет '0123' console.log(normalizeNum(1234, 4)); // выведет '1234'

А вот примеры того, как наша функция будет дополнять до 6-ти цифр:

console.log(normalizeNum(123, 6)); // выведет '000123' console.log(normalizeNum(1234, 6)); // выведет '001234' console.log(normalizeNum(12345, 6)); // выведет '012345' console.log(normalizeNum(123456, 6)); // выведет '123456'

Аналогично можно привести примеры дополнения до 8-ми цифр, до 10 цифр, и так далее.

Наша функция normalizeNum будет выглядеть примерно вот так:

function normalizeNum(num, digitsAmount) { let str = String(num); // код, дополняющий количество цифр нулями до количества из digitsAmount return str; }

Для реализации функции normalizeNum было бы неплохо иметь функцию, которая будет формировать строку, заполненную нужным количеством нулей.

Пусть эта функция будет называться formStr. Посмотрим на ожидаемые нами примеры ее работы:

console.log( formStr('0', 4) ); // выведет '0000' console.log( formStr('0', 3) ); // выведет '000' console.log( formStr('0', 2) ); // выведет '00' console.log( formStr('0', 1) ); // выведет '0' console.log( formStr('0', 0) ); // выведет ''

Если бы у нас была такая функция, то сделать функцию normalizeNum не составило бы труда - мы бы сделали ее вот так:

function normalizeNum(num, digitsAmount) { let str = String(num); return formStr('0', digitsAmount - str.length) + str; }

Объясните работу следующей строки функции normalizeNum:

return formStr('0', digitsAmount - str.length) + str;

Вот так будет выглядеть наша функция formStr:

function formStr(data, length) { // какой-то код }

Допишите недостающий код функции formStr. Потестируйте ее работу.

Возьмите код функции normalizeNum:

function normalizeNum(num, digitsAmount) { let str = String(num); return formStr('0', digitsAmount - str.length) + str; }

Возьмите написанную вами функцию formStr и потестируйте работу функции normalizeNum, например, вот так:

function normalizeNum(num, digitsAmount) { let str = String(num); return formStr('0', digitsAmount - str.length) + str; } function formStr(data, length) { // написанный вами код } console.log(normalizeNum(123, 6)); // выведет '000123' console.log(normalizeNum(1234, 6)); // выведет '001234' console.log(normalizeNum(12345, 6)); // выведет '012345' console.log(normalizeNum(123456, 6)); // выведет '123456'

Потестируйте совместную работу функций normalizeNum и isLucky, например, вот так:

console.log( isLucky(normalizeNum(1203, 4)) ); // выведет true console.log( isLucky(normalizeNum(312, 4)) ); // выведет true console.log( isLucky(normalizeNum(6123, 6)) ); // выведет true console.log( isLucky(normalizeNum(600123, 6)) ); // выведет true console.log( isLucky(normalizeNum(700123, 6)) ); // выведет false console.log( isLucky(normalizeNum(070123, 6)) ); // выведет false

Функция getLuckyTickets

Вспомним теперь код функции getLuckyTickets:

function getLuckyTickets() { let result = []; for (let i = 1001; i <= 999999; i++) { if (isLucky(i)) { result.push(i); } } return result; }

Мы вызывали данную функцию вот так:

console.log(getLuckyTickets());

Давайте теперь будем при вызове функции передавать в нее параметром количество цифр в билетах:

console.log(getLuckyTickets(4)); // ищем билеты с 4-мя цифрами

Пусть передаваемое число попадает в параметр digitsAmount:

function getLuckyTickets(digitsAmount) { // какой-то код }

Теперь перед нами встает некоторая проблема. Посмотрите внимательно на цикл из нашей функции:

for (let i = 1001; i <= 999999; i++) { }

Как вы видите, цикл крутится от числа 1001 до числа 999999. Эти числа, однако, соответствуют той ситуации, когда у нас 6 цифр в билете. Если количество цифр в билете будет иным, то и начало и конец цикла должны быть другими.

Конец цикла получить легко: там должно быть digitsAmount девяток. То есть для 6-ти цифр в билете там будет 6 девяток, для 4-х цифр в билете там будет 4 девятки и так далее.

С началом цикла сложнее. Давайте для начала выпишем соответствия между количеством цифр в билете и началом цикла: 4 - 101, 6 - 1001, 8 - 10001, 10 - 100001 и так далее. Самостоятельно определите логику, по которой формируются данные числа.

Сделайте функцию getLast, которая параметром будет принимать число цифр в билете и возвращать число, соответствующее концу цикла. Потестируйте эту функцию на различных значениях.

Сделайте функцию getFirst, которая параметром будет принимать число цифр в билете и возвращать число, соответствующее началу цикла. Потестируйте эту функцию на различных значениях.

Функция getLuckyTickets

Давайте теперь, имея функции getFirst и getLast, перепишем цикл внутри функции getLuckyTickets так, чтобы начало и конец цикла зависели от количества цифр в билете:

function getLuckyTickets(digitsAmount) { let result = []; let first = getFirst(digitsAmount); let last = getLast(digitsAmount); for (let i = first; i <= last; i++) { // тут будет какой-то код } return result; }

Напишем теперь код внутри цикла, используя там функции normalizeNum и isLucky:

for (let i = first; i <= last; i++) { // Получим нормализованнй номер билета: let ticket = normalizeNum(num, digitsAmount); // Если нормализованный номер счастливый: if (isLucky(ticket)) { result.push(ticket); // запишем счастливый номер в массив } }

Полный код функции getLuckyTickets получится таким:

function getLuckyTickets(digitsAmount) { let result = []; let first = getFirst(digitsAmount); let last = getLast(digitsAmount); for (let i = first; i <= last; i++) { let ticketNum = normalizeNum(num, digitsAmount); if (isLucky(ticketNum)) { result.push(ticketNum); } } return result; }

Соберите весь код вместе, запустите его. Потестируйте общую работу кода для билетов с различным количеством цифр.