<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Сергей Мелюков</title><generator>teletype.in</generator><description><![CDATA[Software Architect]]></description><image><url>https://teletype.in/files/9e/aa/9eaa4658-1257-4cb4-b58c-a36cdeb1a82a.jpeg</url><title>Сергей Мелюков</title><link>https://teletype.in/@smelukov_dev</link></image><link>https://teletype.in/@smelukov_dev?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=smelukov_dev</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/smelukov_dev?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/smelukov_dev?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Fri, 31 Jul 2026 08:32:29 GMT</pubDate><lastBuildDate>Fri, 31 Jul 2026 08:32:29 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@smelukov_dev/codewars-square-every-digit</guid><link>https://teletype.in/@smelukov_dev/codewars-square-every-digit?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=smelukov_dev</link><comments>https://teletype.in/@smelukov_dev/codewars-square-every-digit?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=smelukov_dev#comments</comments><dc:creator>smelukov_dev</dc:creator><title>codewars: square every digit</title><pubDate>Tue, 02 Mar 2021 23:22:36 GMT</pubDate><category>Codewars</category><tt:hashtag>codewars</tt:hashtag><tt:hashtag>js</tt:hashtag><tt:hashtag>javascript</tt:hashtag><tt:hashtag>решениезадач</tt:hashtag><tt:hashtag>алгоритмы</tt:hashtag><description><![CDATA[⚠️ Статья наполнена спойлерами. Если вы хотите сами решить задачу, то вернитесь к статье только после того как решите ее сами или если у вас закончится терпение 😉]]></description><content:encoded><![CDATA[
  <blockquote>⚠️ Статья наполнена спойлерами. Если вы хотите сами решить задачу, то вернитесь к статье только после того как решите ее сами или если у вас закончится терпение 😉</blockquote>
  <p>Недавно я откапал свой логин/пароль к <a href="https://www.codewars.com/dashboard" target="_blank">codewars</a> и наткнулся на <a href="https://www.codewars.com/kata/546e2562b03326a88e000020" target="_blank">задачку</a> с таким описанием:</p>
  <pre>You are asked to square every digit of a number and concatenate them.
For example, if we run 9119 through the function, 811181 will come out, because 9^2 is 81 and 1^2 is 1.
Note: The function accepts an integer and returns an integer</pre>
  <p>Смысл в том, что на вход функции поступает число, каждый разряд которого нужно возвести в квадрат. Полученные квадраты разрядов нужно объединить и вернуть из функции.</p>
  <p>На входе и на выходе должны быть именно числа (<code>typeof x === &#x27;number&#x27;</code>). Примеры:</p>
  <pre>fn(3212) // 9414
fn(9119) //811181</pre>
  <p>Я решил задачку по-своему - так, как считал оптимальным, затем посмотрел как решили другие, сделал определенные выводы, которые показались мне интересными. Затем <a href="https://t.me/smelukov_dev/81" target="_blank">задал вопрос</a> подписчикам моего telegram-канала - как они решили бы эту задачу. Собрал варианты, которые они предложили, сгруппировал их, и в этой статье хочу сравнить их. Все решения будем сравнивать относительно моего (его приведу ближе к концу).</p>
  <blockquote>Замеры я производил на основе 1,000,000 заранее сгенерированных чисел от 0 до 1,000,000</blockquote>
  <p>Итак. Конечно же, первое, что приходит в голову - это решение при помощи строк. Оно просто и короткое:</p>
  <ul>
    <li>превратили число в строку</li>
    <li>смапили символы-разряды на их квадраты</li>
    <li>соединили</li>
  </ul>
  <p>Но здесь не все так однозначно и решение на строках может быть разным.</p>
  <p>Рассмотрим пример:</p>
  <pre>const fn = val =&gt; +[...&#x27;&#x27; + val].map(n =&gt; n ** 2).join(&#x27;&#x27;);</pre>
  <p>Это простое решение не эффективно с точки зрения утилизации ресурсов. </p>
  <p>Здесь мы делаем много лишних действий:</p>
  <ul>
    <li>преобразуем число в строку</li>
    <li>преобразуем строку в массив</li>
    <li>каждый символ строки преобразуем в число (<code>n ** 2</code>)</li>
    <li>преобразуем получившийся массив в строку</li>
    <li>преобразуем получившуюся строку в число</li>
  </ul>
  <p>Этот вариант в 6.9 медленнее эталона 📉</p>
  <p>Из этого делаем вывод, что преобразования - это плохо для производительности и нам нужно постараться свести их к минимуму.</p>
  <p>Попробуем еще одно решение на строках, но с меньшим количеством преобразований:</p>
  <pre>function fn(val) {
  let res = &#x27;&#x27;;
  val = val + &#x27;&#x27;;
  
  for (let i = 0; i &lt; val.length; i++) {
    res += val[i] ** 2;
  }
  
  return +res;
}</pre>
  <ul>
    <li>преобразуем число в строку (<code>val + &#x27;&#x27;</code>)</li>
    <li>преобразуем каждый символ в число и обратно (<code>res += val[i] ** 2</code>)</li>
    <li>преобразуем строку в число (<code>+res</code>)</li>
  </ul>
  <p>Этот вариант уже в 3.6 раза медленнее эталона 📉</p>
  <p><a href="https://twitter.com/rdvornov" target="_blank">Роман Дворнов</a> предложил интересное решение</p>
  <pre>function fn(val) {
  return +String(val).replace(/./g, m =&gt; m * m);
}</pre>
  <p>Здесь мы используем замену по регулярному выражению, чтобы заменить все числа на их квадраты. Не смотря на небольшое количество преобразований, оно в 10.9 раз медленнее эталона из-за регулярных выражений 📉</p>
  <p>Так же Роман предложил развитие идеи:</p>
  <pre>const xs = [&quot;0&quot;, &quot;1&quot;, &quot;4&quot;, &quot;9&quot;, &quot;16&quot;, &quot;25&quot;, &quot;36&quot;, &quot;49&quot;, &quot;64&quot;, &quot;81&quot;];

function fn(val) {
  return +String(val).replace(/[2-9]/g, m =&gt; xs[m]);
}</pre>
  <p>Суть в том, что мы заранее высчитываем квадраты чисел от 0 до 9 и записываем их в массив в виде <strong>строк</strong> (это важно!).</p>
  <p>В самой функции мы заменяем числа от 2 до 9 на их предрассчитанные значения из массива. Единицы и нули не имеет смысла заменять, т.к. они останутся без изменений в какую бы степень мы их не возвели.</p>
  <p>Предрассчитанные квадраты чисел хранятся в массиве в виде строк чтобы при замене не было приведения числа к строке.</p>
  <p>Этот вариант в 9.8 раз медленнеее эталона 📉</p>
  <p>Не смотря на низкую производительность, мы вернемся к этому варианту позже.</p>
  <p>Очевидно, что преобразования на строках - это не лучшее решение с точки зрения производительности.</p>
  <p>Если важна скорость и что-то можно сделать при помощи математики, то лучше деать это при помощи математики.</p>
  <p>Возьмем для примера число <code>3212</code>, оно должно превратиться в <code>9414</code>.</p>
  <p><strong>Как можно проделать с ним все нужные нам операции без пробразований?</strong></p>
  <p>Число можно разделить на разряды:</p>
  <ul>
    <li>9 - разряд тысяч</li>
    <li>4 - разряд сотен</li>
    <li>1 - разряд десятков</li>
    <li>4 - разряд единиц</li>
  </ul>
  <p><strong>Как собрать число имея каждый разряд по отдельности?</strong></p>
  <p>Необходимо найти сумму произведений каждого разряда на значение этого разряда. Проще говоря:</p>
  <pre>9414 = (4 * 1) + (1 * 10) + (4 * 100) + (9 * 1000)</pre>
  <p><strong>Как получить то же самое из числа 3212?</strong></p>
  <pre>9414 = (2^2 * 1) + (1^2 * 10) + (2^2 * 100) + (3^2 * 1000)</pre>
  <p><strong>Как реализовать это в виде кода?</strong></p>
  <pre>function fn(num) {
  let multiplier = 1;
  let res = 0;
  
  while (num !== 0) {
    const digit = num % 10;
    const sqr = digit ** 2;
    
    num = ~~(num / 10);
    res += sqr * multiplier;
    multiplier *= (sqr &lt; 10 ? 10 : 100);
  }
  
  return res;
}</pre>
  <blockquote>Если у вас есть вопросы по логике кода, пожалуйста, пишите в комменты.</blockquote>
  <p>Подписчики предлагали похожие решения, например:</p>
  <pre>function fn(n) {
  let pow = 0;
  const getNum = () =&gt; {
    let res = Math.floor(n / (10 ** pow));
    return res &gt; 0 ? res % 10 : 0;
  }
  
  let num;
  let result = 0;
  let resultPow = 0;
  
  while ((num = getNum()) &gt; 0) {
    result += (num * num) * (10 ** resultPow);
    resultPow += (num &gt; 3) ? 2 : 1;
    pow++;
  }
  
  return result;
}</pre>
  <p>Но не смотря на то, что здесь нет преобразований, этот вариант в 6.2 раз медленнее эталона и в 1.7 раз медленне оптимального варианта со строками 📉. Это позволяет сделать вывод, что наличие большого количества операций и вызова функций (добавляют манипуляций со стеком) может нивелировать профит от отсутствия преобразований.</p>
  <p>Ближе всего к моему варианту был такой пример:</p>
  <pre>function fn6(number) {
  let result = 0;
  let signs = 1;
  
  while (number &gt; 0) {
    let digit = number % 10;
    
    result += digit * digit * signs;
    signs *= digit &gt; 3 ? 100 : 10;
    number = Math.floor(number / 10);
  }
  
  return result;
}</pre>
  <p>Он всего на 10% медленнее моего . Но за счет чего?</p>
  <p>Дело в том, что <code>Math.floor</code> - это <a href="https://262.ecma-international.org/6.0/#sec-math.floor" target="_blank">дополнительная логика под капотом</a> и если заменить <code>Math.floor(number / 10)</code> на <code>~~(number / 10)</code>  то мы получим ту же производительность.</p>
  <h2>Бонус</h2>
  <p>А теперь давайте вернемся к варианту, который предлагал Роман Дворнов и позаимствуем оттуда идею с предрассчитанными квадратами, объединим с моим вариантом и получим более производительную функцию:</p>
  <pre>const xn = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81];

function fn(num) {
  let multiplier = 1;
  let res = 0;
  
  while (num !==0) {
    const digit = num % 10;
    
    num = ~~(num / 10);
    res += xn[digit] * multiplier;
    multiplier *= (num &lt; 4 ? 10 : 100);
  }
  
  return res;
}</pre>
  <p>Этот вариант на ~13% быстрее моего изначального варианта за счет того, что мы избавились от математической операции 📈</p>
  <p>Ну а позже Роман предложил еще один вариант, до которого у меня самого дошли только мысли, но не руки - заменить часть ариметики на побитовые операции:</p>
  <pre>const xn = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81];

function fn(num){
  let multiplier = 1;
  let res = 0;
  
  while(true) {
    const digit = num % 10;
    
    res += xn[digit] * multiplier;
    
    if (num === digit) break;
    
    num = ~~(num / 10);
    multiplier = digit &lt; 4 ? 
      (multiplier &lt;&lt; 3) + (multiplier &lt;&lt; 1) :
      (multiplier &lt;&lt; 6) + (multiplier &lt;&lt; 5) + (multiplier &lt;&lt; 2);
  }
  
  return res;
}</pre>
  <p>Плюс ко всему, за счет <code>break</code>, мы можем не высчитывать <code>num</code> и <code>multiplier</code> на последней итерации.</p>
  <p>Хотя такой код и труднее читать, он на ~20% быстрее моего изначального варианта 📈</p>
  <h2>Подводя итог</h2>
  <p>К сожалению, JS в какой-то степени расслабляет и часто мы пишем простой, но не производительный код.</p>
  <p>Если вашему коду жизненно важна производительность, то ее надо буквально &quot;выгрызать&quot; любыми доступными способами, экономя любые операции. Но если нужно просто написать производительный код, то пишите его так, чтобы не было лишних операций и тем более ненужных преобразований. Соблюдайте баланс между производительностью и читаемостью.</p>
  <tt-tags>
    <tt-tag name="codewars">#codewars</tt-tag>
    <tt-tag name="js">#js</tt-tag>
    <tt-tag name="javascript">#javascript</tt-tag>
    <tt-tag name="решениезадач">#решениезадач</tt-tag>
    <tt-tag name="алгоритмы">#алгоритмы</tt-tag>
  </tt-tags>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@smelukov_dev/rt-count-on-me</guid><link>https://teletype.in/@smelukov_dev/rt-count-on-me?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=smelukov_dev</link><comments>https://teletype.in/@smelukov_dev/rt-count-on-me?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=smelukov_dev#comments</comments><dc:creator>smelukov_dev</dc:creator><title>return true: countOnMe</title><pubDate>Sun, 28 Feb 2021 20:23:12 GMT</pubDate><category>return true</category><tt:hashtag>returntrue</tt:hashtag><tt:hashtag>js</tt:hashtag><tt:hashtag>javascript</tt:hashtag><description><![CDATA[Привет! Сегодня разбираемся с задачкой countOnMe из второго сезона RT.]]></description><content:encoded><![CDATA[
  <p>Привет! Сегодня разбираемся с задачкой <code>countOnMe</code> из второго сезона <a href="https://alf.nu/ReturnTrue" target="_blank">RT</a>.</p>
  <blockquote>⚠️ Статья наполнена спойлерами. Если вы хотите сами решить задачу, то вернитесь к статье только после того как решите ее сами или если у вас закончится терпение 😉</blockquote>
  <h2>countOnMe1</h2>
  <pre>function countOnMe(x) {
  if (!(x instanceof Array))
    throw &#x27;x must be an array.&#x27;;

  for (var i = 0; i &lt; 20; i++) {
    if (x[i] != i) {
      throw &#x27;x must contain the numbers 0-19 in order&#x27;;
    }
  }

  return true;
}</pre>
  <p>Задача в том, чтобы передать в функцию массив, состоящий из цифр от 0 до 19.</p>
  <p>Конечно, можно просто передать <code>[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]</code>, но это было бы слишком просто и очевидность этого решения намекает на то, что есть решение короче 51 байта.</p>
  <p>Наша задача сделать так, чтобы условие <code>x[i] != i</code> никогда не выполнялось.</p>
  <p>Можно попробовать создать <code>Proxy</code>, который будет перехватывать все попытки обратиться к какому-либо свойству и возвращать обратно имя свойства:</p>
  <pre>const x = new Proxy([], {
  get: (target, key) =&gt; key
});
x[1] // &#x27;1&#x27;
x[100] // &#x27;100&#x27;
x[&#x27;hi&#x27;] // &#x27;hi&#x27;</pre>
  <p>Таким образом, не важно сколько у нас элементов в массиве, на все попытки обратиться к элементу по индексу, мы будем возвращать этот индекс обратно. В итоге, используя <code>new Proxy([],{get:(t,k)=&gt;k})</code>, мы получаем <code>true</code> за 28 байт ✅</p>
  <blockquote>Мы считаем именно байты, а не символы. Так например, один символ эмодзи будет занимать несколько байт (от 2 и более)</blockquote>
  <p>Видим в лидерборде, что лучшее решение - это 18 байт, поэтому думаем как можно сократить решение.</p>
  <p>Еще один вариант решения основан на том, что мы можем сгенерировать массив указанной длины: <code>Array(20)</code></p>
  <p>Но это пустой массив, поэтому он не пройдет все проверки. Тем не менее, из этого массива мы можем получить ключи:</p>
  <pre>const keys = [...Array(20).keys()];
keys // [0,1,2,...,17,18,19]</pre>
  <p>Используем spread-оператор потому что <code>Array#keys()</code> возвращает не массив, а итерируемый объект.</p>
  <p>Получаем <code>true</code> за 21 байт ✅, но это все еще не 18, поэтому думаем дальше.</p>
  <p><strong>Как еще можно получить массив из 20 элементов?</strong></p>
  <p>Можно применить подход с получением ключей, но будем получать не ключи массива, а ключи строки:</p>
  <pre>const keys = Object.keys(&#x27;это строка в 20 байт&#x27;);
keys // [0,1,2,...,17,18,19]</pre>
  <p>Теперь нам осталось понять как сгенерировать строку длиной минимум в 20 байт (можно и больше, просто в задаче проверяются только первые 20). Вот варианты того, как это можно сделать:</p>
  <pre>Object.keys(9**-9+&#x27;&#x27;) // решение в 21 байт ✅
Object.keys(9e19+&#x27;&#x27;) // решение в 20 байт ✅
Object.keys(Date()) // решение в 19 байт ✅</pre>
  <p>Но 19 байт это все еще не 18.</p>
  <p>Давайте вспомним про преобразование типов, которое мы <a href="https://teletype.in/@smelukov_dev/rt-length" target="_blank">применили для решения задачи length</a> и используем его снова: </p>
  <pre>Set+1 // &#x27;function Set() { [native code] }&#x27;
Object.keys(Set+1) // [0,1,2,3,...,29,30,31,32]</pre>
  <p>Это и есть решение в 18 байт ✅</p>
  <h3>Решения</h3>
  <ul>
    <li><code>[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]</code> - 51</li>
    <li><code>new Proxy([],{get:(i,k)=&gt;k})</code> - 28</li>
    <li><code>[…Array(20).keys()]</code> - 21</li>
    <li><code>Object.keys(9**-9+&#x27;&#x27;)</code> - 21</li>
    <li><code>Object.keys(9e19+&#x27;&#x27;)</code> - 20</li>
    <li><code>Object.keys(Date())</code> - 19</li>
    <li><code>Object.keys(Set+1)</code> - 18 🏆</li>
  </ul>
  <h2>countOnMe2</h2>
  <p>Рассмотрим еще один вариант этого задания:</p>
  <pre>function countOnMe2(x) {
  if (!(x instanceof Array))
    throw &#x27;x must be an array.&#x27;;

  for (var i = 0; i &lt; 1000; i++) {
    if (x[i] !== i) {
      throw &#x27;x must contain the numbers 0-999 in order&#x27;;
    }
  }

  return true;
}</pre>
  <p>Смысл тот же, но теперь нам нужен массив не из 20 элементов, а из 1000. Плюс ко всему, здесь используется строгое сравнение <code>x[i] !== i</code>, поэтому массив из строк нам уже не подойдет. Можем попробовать вариант с <code>Proxy</code>: <code>new Proxy([],{get:(t,k)=&gt;+k}). Получаем true в 29 байт ✅</code></p>
  <p>Заметьте, что здесь мы возвращаем не просто <code>k</code>, а <code>+k</code>, чтобы привести строковый ключ к числу, чтобы сработало строгое сравнение. Видим, что лучшее решение состоит из 22 байт, поэтому думаем дальше.</p>
  <p>Можем попробовать вернуться к решению с ключами массива: <code>[...Array(1000).keys()] // [0,1,2,3,...,998,999]</code>. Это <code>true</code> за 23 байта ✅</p>
  <p>Нужно &quot;выиграть&quot; еще один байт. Идея в том, что <code>1000</code> можно записать как <code>1e3</code>: <code>1000 === 1e3 // true</code></p>
  <p>Заменяем <code>1000</code> на <code>1e3</code>: <code>[...Array(1e3).keys()]</code> и получаем <code>true</code> за 22 байта ✅</p>
  <h3>Решения</h3>
  <ul>
    <li><code>new Proxy([],{get:(i,k)=&gt;+k})</code> - 29</li>
    <li><code>[...Array(1000).keys()]</code> - 23</li>
    <li><code>[...Array(1e3).keys()]</code> - 22 🏆</li>
  </ul>
  <h2>countOnMe3</h2>
  <p>И еще одна вариация этой задачи выглядит так:</p>
  <pre>function countOnMe3(x) {
  var arrayElements = 1000;

  if (!(x instanceof Array))
    throw &#x27;x must be an Array&#x27;;

  for (var i = 0; i &lt; arrayElements; i++)
    if (x[i] != i)
      throw &#x27;x must contain the numbers 0-999 in order&#x27;;

  for (element of x)
    if (element != --arrayElements)
      throw &#x27;x must contain the numbers 999-0 in order&#x27;;

  if (x.length !== 0)
    throw &#x27;x must be empty&#x27;;

  return true;
}</pre>
  <p>Судя по коду, нам нужно передать такой массив, который <strong>одновременно</strong> содержит числа от 0 до 999, от 999 до 0 и размер этого массива должен равняться нулю. Это три противоречащих друг-другу условия и это означает, что нам нужно придумать что-то на основе особенностей языка.</p>
  <p>Обратим внимание на то, что второй проход по массиву происходит при помощи <code>for-of</code>, который использует итераторы, а значит нам нужен массив, в котором будут содержаться элементы от 0 до 999, а <code>Symbol.iterator</code> этого массива должен генерировать обратную последовательность. Таким образом мы покрываем все условия кроме последнего, а значит нужно придумать что-то еще.</p>
  <p>Первое решение состоит в том, чтобы передать пустой массив, прототипом которого является массив с числами от 0 до 999:</p>
  <pre>const a = [];
a.__proto__=[...Array(1e3).keys()]
a // [ length: 0, __proto__: [0,1,2,3,...,998,999] ]</pre>
  <p>Таким образом элементы от 0 до 999 будут доступны через прототип, а вот <code>Symbol.iterator</code> будет выполняться в контексте пустого массива, а значит ни одной итерации <code>for-of</code> не будет выполнено. Ну и <code>length</code> пустого массив будет равен нулю. Итого, при помощи <code>a=[],a.__proto__=[...Array(1e3).keys()]</code> получает <code>true</code> за 39 байт ✅</p>
  <p>В лидерборде мы видим, что лучшее решение занимает 34 байта, а значит нам нужно придумать что-то еще.</p>
  <p>Я предлагаю пойти по другому пути и использовать уже знакомый нам подход с <code>Proxy</code>, но возвращать мы будем не просто переданный ключ, а <strong>ключ или существующее свойство</strong>. Посмотрите на код:</p>
  <pre>const x = new Proxy([], {
  get: (target, key) =&gt; target[key] ?? key
});
x[0] // &#x27;0&#x27;
x[100] // &#x27;100&#x27;
x[Symbol.iterator] // function () {...}
x.length // 0</pre>
  <p>Обратите внимание на конструкцию <code>target[key] ?? key</code>, она использует <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator" target="_blank">nullish coalescing operator </a>который означает, что левая часть будет использована только если она не <code>null</code> и не <code>undefined</code>, иначе будет использована правая часть. Посмотрите на примеры выше чтобы понять как это может нам пригодиться. Если нужного нам ключа нет в массиве, то мы возвращаем сам ключ, а если есть, то возвращаем значение по этому ключу. Таким образом мы удовлетворим все проверки в задачи:</p>
  <ul>
    <li><code>x instanceof Array</code> будет <code>true</code>, не смотря на то, что это <code>Proxy</code></li>
    <li><code>x[i] != i</code> внутри <code>for (var i = 0; i &lt; arrayElements; i++)</code> никогда не сработает, потому что прокси всегда будет возвращать запрошенный ключ</li>
    <li><code>for (element of x)</code> не выполнит ни одной итерации, потому что <code>Symbol.iterator</code> выполнится в контексте пустого массива</li>
    <li><code>x.length</code> будет ноль, т.к. массив пуст</li>
  </ul>
  <p>Итого, при помощи <code>new Proxy([],{get:(t,k)=&gt;t[k]??k})</code> получаем <code>true</code> за 34 байта ✅</p>
  <h3>Решения</h3>
  <ul>
    <li><code>a=[],a.__proto__=[...Array(1e3).keys()]</code> - 39</li>
    <li><code>new Proxy([],{get:(t,k)=&gt;t[k]??k})</code> - 34 🏆</li>
  </ul>
  <p></p>
  <p>Вот мы и рассмотрели 3 варианта задачи <code>countOnMe</code> c абсолютно разными подходами к решению, зачастую не самыми очевидными. Пробуйте, экспериментируйте, ищите решения, даже если кажется, что ничего нельзя придумать.</p>
  <tt-tags>
    <tt-tag name="returntrue">#returntrue</tt-tag>
    <tt-tag name="js">#js</tt-tag>
    <tt-tag name="javascript">#javascript</tt-tag>
  </tt-tags>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@smelukov_dev/rt-length</guid><link>https://teletype.in/@smelukov_dev/rt-length?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=smelukov_dev</link><comments>https://teletype.in/@smelukov_dev/rt-length?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=smelukov_dev#comments</comments><dc:creator>smelukov_dev</dc:creator><title>return true: length</title><pubDate>Sat, 27 Feb 2021 11:46:57 GMT</pubDate><category>return true</category><tt:hashtag>returntrue</tt:hashtag><tt:hashtag>javascript</tt:hashtag><tt:hashtag>js</tt:hashtag><description><![CDATA[Привет! Разбираем решение задачки length из второго сезона RT.]]></description><content:encoded><![CDATA[
  <p>Привет! Разбираем решение задачки <code>length</code> из второго сезона <a href="https://alf.nu/ReturnTrue" target="_blank">RT</a>.</p>
  <blockquote>⚠️ <strong>Статья наполнена спойлерами</strong>. Если вы хотите сами решить задачу, то вернитесь к статье только после того как решите ее сами или если у вас закончится терпение </blockquote>
  <p><strong>Задача:</strong></p>
  <pre>function length(x) {
  return typeof x !== &#x27;object&#x27; &amp;&amp; !Array.isArray(x) &amp;&amp; x.length == 4
}</pre>
  <p>Нам необходимо передать такой аргумент, который и <strong>не объект</strong> и <strong>не массив</strong>, но его свойство <code>length</code> равно <code>4</code>.</p>
  <p>Передать <code>{ length: 4 }</code> мы не можем, потому что это объект. <code>[1,2,3,4]</code> тоже не сработает.</p>
  <p><strong>Что кроме массивов имеет свойство <code>length</code> и не является при этом объектом?</strong></p>
  <ul>
    <li>Функции</li>
    <li>Строки</li>
  </ul>
  <p>Свойство <code>length</code> у функции возвращает количество параметров этой функции:</p>
  <pre>function f(a,b,c,d) {}
console.log(f.length); // 4</pre>
  <p>Пробуем передать <code>function(a,b,c,d){}</code> и получаем <code>true</code> за 19 байт ✅</p>
  <p>Но, минимальный длина решения в лидерборде - 5 байт, а значит нам нужно придумать что-то еще. Попробуем сократить функцию до <code>(a,b,c,d)=&gt;1</code> - это 12 байт ✅</p>
  <p>Лучше, но все равно не то.</p>
  <p>Попробуем вариант со строками, например <code>&#x27;1234&#x27;</code> - получаем <code>true</code> за 6 байт ✅</p>
  <p>Это еще лучше, но все еще не 5 байт.</p>
  <p>Тут мы оказываемся в ситуации, когда ни функции, строковые литералы нам не подходят.</p>
  <p><strong>Как получиться строку длиной в 4 байта потратив при этом 5 байт?</strong></p>
  <p>Можно воспользоваться преобразованием типов и привести что-нибудь к строке.</p>
  <p>Подробнее <a href="https://medium.com/developers-arena/type-coercion-in-javascript-c973b369b272" target="_blank">здесь</a> (попроще) и <a href="https://2ality.com/2019/10/type-coercion.html" target="_blank">здесь</a> (посложнее).</p>
  <pre>1 + &#x27;&#x27; // &#x27;1&#x27;
[] + &#x27;&#x27; // &quot;&quot;
NaN + &#x27;&#x27; // &#x27;NaN&#x27;
undefined + &#x27;&#x27; // &#x27;undefined&#x27;
true + &#x27;&#x27; // &#x27;true&#x27;</pre>
  <p>Строка <code>&#x27;true&#x27;</code> как раз состоит из 4 байт, это то, что нам нужно!</p>
  <p>Но <code>true+&#x27;&#x27;</code> - это 7 байт, но мы-то с вами знаем, что <code>true</code> можно еще записать как <code>!0</code>, поэтому попробуем сократить: <code>!0+&#x27;&#x27;</code> - получаем <code>true</code> за желанные 5 байт ✅</p>
  <h3><strong>Хронология решений</strong></h3>
  <ul>
    <li><code>function(a,b,c,d){}</code> - 19</li>
    <li><code>(a,b,c,d)=&gt;1</code> - 12</li>
    <li><code>&#x27;1234&#x27;</code> - 6</li>
    <li><code>true+&#x27;&#x27;</code> - 7</li>
    <li><code>!0+&#x27;&#x27;</code> - 5 🏆</li>
  </ul>
  <tt-tags>
    <tt-tag name="returntrue">#returntrue</tt-tag>
    <tt-tag name="javascript">#javascript</tt-tag>
    <tt-tag name="js">#js</tt-tag>
  </tt-tags>

]]></content:encoded></item></channel></rss>