Популярный подход к программированию состоит в том, что самый быстрый код, который вы можете написать, - это вообще не писать кода. Более компактный код по определению более эффективен, но сосредоточение внимания исключительно на объеме синтаксиса может легко упустить из виду структуры внутри этого синтаксиса; а именно используемые структуры данных.

То, что вы пишете, так же важно, как и то, что вы пишете. Хорошим примером, который блестяще демонстрирует эти концепции, является проблема Иосифа Флавия. Проблема названа в честь Иосифа Флавия, библейского деятеля, который оказался в окружении римлян вместе с сонмом еврейских солдат.

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

В самом простом случае цель решения проблемы Иосифа Флавия состоит в том, чтобы решить проблему единственного выжившего в группе из «n» человек.

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

Этот процесс кажется немного сложным, и это может быть. В отличном сообщении в блоге Амандо Абреу подробно описано, как программно выполнить это вычисление, которое можно прочитать здесь:



Если мы взглянем на отрывок из предоставленного кода, мы увидим, что решение Amando предоставляет средства для отслеживания состояния каждого участника в рамках общего процесса исключения:

var kill = function(arr){
  if (arr.length < 2){
    // This is our last soldier alive.
    return arr;
  }
  var survivors = arr.filter((soldier, index) => index % 2 == 0);
  if (arr.length % 2 !== 0){
    // Add the last person the start
    // if the number of people is odd.
    survivors.unshift(survivors.pop());
  }
  return kill(survivors);
}

Это разумное решение проблемы, но что, если нам нужен только окончательный ответ в кратчайшие сроки и за наименьшее количество шагов?

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

Проблема Иосифа Иосифа освещалась на Numberphile, отличном канале YouTube, посвященном математике. В их обзоре мое внимание было обращено на очень любопытное и выгодное свойство математики, задействованной в этой конкретной задаче.

Ответ на эту проблему можно вычислить, преобразовав количество участвующих людей в двоичную систему, а затем переместив крайний левый бит на место в правой части. Целое число, представленное новой двоичной строкой, всегда будет решением проблемы.

Зная это, мы можем использовать структуры данных в Number и String, чтобы значительно сократить объем кода, который мы пишем, как показано ниже:

const josephus = (n) => {
  /*
   *  If we have received a valid number, convert it
   *  to a binary string using a radix of 2.
   *  Move the left-most bit to the one's place.
   *  Return the integer equivalent.
   */
  if (n && !isNaN(n) && n > 0) {
    let bin = (n).toString(2)
    let survivor = bin.slice(1) + bin.charAt(0)
    return parseInt(survivor, 2)
  }
}

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

Есть много способов достичь того же результата, что и делает программирование таким увлекательным, выразительным и индивидуальным. Развитие знаний не только о том, как написать решение, но и о том, что писать (и в каком объеме) - это бесконечное дерево навыков, которое будет постоянно строиться в ходе нашей карьеры.

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

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

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

Чтобы посмотреть отличное видео Numberphile по этой теме, вы можете посмотреть его ниже: