Олимпиада для котов

Вроде работает. Кто-нибудь из гуру гляньте пжл. Может можно оптимизировать?

Сводка

var getYears = function (yearBegin, yearEnd, sum) {
var array = [];
for (i=yearBegin; i<=yearEnd; i++) { //Перебираем годы
var year = String(i); //Переводим год из числа в строку
var sumOfDigits = 0; //Задаём переменную, где будем складывать цифры из года
for (j=0; j<=year.length-1; j++) { //Перепираем каждую цифру в году
sumOfDigits+=parseInt(year[j], 10);//Суммируем цифры в году
}
if (sumOfDigits == sum) {//Сравниваем сумму цифр в году с sum
array.push(i);//Если они равны, то добавляем этот год в массив
}
}
return array;
}

смотря что под оптимизацией имеется ввиду.
из того что преподают в курсах уже нормально.

Товарищи, помогите, пожалуйста, разобраться.

В первом сообщении Roman1 привел свое решение:

var getYears = function (year, yearEnd, sumYear) {
  var olymp = [];
  for (i = year; i <= yearEnd; i++) {
    var yearStr = String(i);
    var sumYe = Number(yearStr[0]) + Number(yearStr[1]) + Number(yearStr[2]) + Number(yearStr[3]);
    if (sumYe === sumYear) {
      olymp.push(i);
    }
  }
  return olymp;
}

Объясните, пожалуйста, зачем нужны вот эти участки кода и как они работают:

var yearStr = String(i);
var sumYe = Number(yearStr[0]) + Number(yearStr[1]) + Number(yearStr[2]) + Number(yearStr[3]);

Буду признателен, если кто-нибудь растолкует подробно.

Пусть будет число 1234
var yearStr = String(i); // "1234" строка

Преобразование типа данных к строке
А строку уже можно рассматривать как массив (ну вот работает так строка как неразбитый массив, имеет некоторые схожие методы), взяв от нее N - элемент
Мы живем в третьем тысячелетии, поэтому нас интересуют четырехзначные цифры-строки (Император Человечества негодуэ, т.к. эту прогу не использовать в 40к году).

yearStr[0] + yearStr[1] + yearStr[2] + yearStr[3] // "1" + "2" + "3" + "4"

И теперь берем 0, 1, 2, 3 элемент числа-строки и складываем. А чтобы не произошла конкатенация строк, приведем взятые числа-строки к числам

Number( элемент_числа-строки ) // 1 + 2 + 3 + 4

1 лайк

Hierumo, спасибо за ответ.
Логику преобразования (из строк в числа) понял.

Только я не понял зачем было вообще приводить данные — начальный и конечный годы к строке. Они же изначально приходят нам в виде чисел, — зачем нужна операция приведения числа к строке на первом шаге? Без нее никак никак не получится решить задачу?

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

ясно, спасибо за разъяснение!

Пришел к такому решению.

var getYears = function (startYear, endYear, digit) {

var period = [startYear]; // создаем массив, сразу помещаем в него начальный год
for (i = 0; period[period.length - 1] < endYear; i++) { // наполняем массив пока не достигнем значения аргумента endYear
  period.push(period[i] + 1);
}

var currentYear; // создаем отдельную переменную для работы с каждым из элементов
var resultYears = []; // создаем массив, в который сохранятся подходящие значения

for (n = 0; n <= period.length - 1; n++) { // перебираем развернутый массив period
  currentYear = String(period[n]); // каждый элемент переводим в строку
  var sum = 0; // назначаем переменную для подсчета суммы в элементе
  for (j = 0; j <= currentYear.length - 1; j++) { // перебираем строку как массив
    sum += Number(currentYear[j]); // каждый символ приводим к числу и складываем
    }
  if (sum === digit) { // проверяем, совпадает ли сумма с аргументом digit
    resultYears.push(period[n]); // если да - отправляем в итоговый массив
    }
}
return resultYears; // возвращаем массив найденных годов как результат функции getYears
}

Решение без перевода числа в строку и обратно, только на циклах.
Использование перевода, мне кажется, утяжеляет код.
Ну и этот вариант универсален - мало ли где будет Кекс в 40к году )

var getYears = function(year1, year2, num) {
var newArray = [];
while(year1 <= year2) {
var sum = 0;
for (var i = year1; i > 0; i = parseInt(i/10)) {
var n = i % 10;
sum += n;
}
if (sum == num) {
newArray.push(year1);
}
year1++;
}
return newArray;
}

var getYears = function(firstY, lastY, numb) {
var olimp = [];
for (var i = firstY; i <= lastY; i++) {
 var sum = 0;
 var yearStr = String(i);
 for (var j = 0; j < yearStr.length; j++) {
  sum += Number(yearStr[j]); 
  }
  if(sum === numb) {
     olimp.push(i);
  }
}
 return olimp;
}

Такое вот решение получилось.

1 лайк
const getYears = function (firstYear, lastYear, sumNumbers) {
  const goodYears = [];

  [...Array(lastYear + 1 - firstYear).keys()].forEach(item => {
    const currYear = item + firstYear;
    const arrYear = (currYear).toString().split('');
    const sumYear = arrYear.reduce((acc, curr) => +acc + +curr);

    if (sumYear === sumNumbers) goodYears.push(currYear);
  });

  return goodYears;
};
1 лайк

var getYears = function (startYear, endYear, sumYear) {
var masYear = []
for (var i = startYear; i <= endYear; i ++) {
var sum = i % 10 + Math.floor(i / 10) % 10 + Math.floor(i / 100) % 10 + Math.floor(i / 1000);

if (sum === sumYear) {
  masYear.push(i);
}

}
return masYear;
}

1 лайк
Как обычно через reduce
const getYears = (yearToStart, yearToEnd, neededSum) => {
  let initialArr = []
  
  for (let i = yearToStart; i <= yearToEnd; i++) {
    const sumInYear = String(i).split('').reduce((acc, item) => acc + Number(item), 0);
    (sumInYear === neededSum) ? initialArr.push(i) : initialArr;
  }
  
  return initialArr;
};

нормально, но слишком много плюсов…+ много доп переменных - усложняет все это читаемость кода

До чего смог додуматься. :disappointed_relieved:

var getYears = function (firstYear, lastYear, sum) {
    var massive = [],
        newMassive = [];
  for (var i = firstYear; i <= lastYear; i++) {
    massive.push(String(i));
  }
  for (var j = 0; j < massive.length; j++) {
      var answer = 0,
          result = massive[j];
      for (var z = 0; z < result.length; z++) {
        for (var x = 1; x <= 9; x++) {
          if (result[z] == x) {
            answer += x;
            var smell = massive[j];
          }
        }
      }
      if (answer == sum) {
        newMassive.push(+smell);
      }
  }
  return newMassive;
}

Видел похожее, но мне мое больше нравится

var getYears = function (startYears, endYears, hasNumber) {
  var needYears = [];
  
  for (var i = startYears, o = 0; i <= endYears; i++, o = 0) {
    
    i = String(i);    
    
    for (var j = 0; j < i.length; j++) { o += Number(i[j]) }
    
    i = Number(i);
    
    if (o === hasNumber) { needYears.push(i) }
  }
  return needYears;
}
const getYears = (startYear, endYear, sum) => {
  const result = [];
  for (let i = startYear; i <= endYear; i++) {
    String(i).split('').map(item => +item).reduce((item, acc) => item + acc) === sum && result.push(i);
  }
  return result;
};
1 лайк

гениально!
подскажите почему result.push(i) всегда true отдает? а то чувствую чет от меня уходит. типа объект (ну т.к. метод это функция, а это объект) при логическом преобразовании всегда true, поэтому, да?

Push возвращает новую длину массива, а это всегда положительное число и == true.

1 лайк

Вот что вышло:

var getYears = function(yearStart, yearEnd, number) {    
  var years = [];
  for (var i = yearStart; i <= yearEnd; i++) { 
    var sum = 0;
    var yearString = String(i);
    for (var j = 0; j < yearString.length; j++) {
      var yearNumber = Number(yearString[j]);
      sum += yearNumber;
      }
    if (sum == number) {
      years.push(i);
      }
    }
  return years;
  }