Developer's notes
33 subscribers
68 photos
4 videos
74 links
Пишу обо всём и ни о чём, могу и о программировании
Download Telegram
Попроще

Честно признаюсь: предыдущая задача – сложная. Решить её без практики строковых/backtrace алгоритмов, и, тем паче, в рамках собеседования, – маловероятно. Рассмотрим задачу попроще, которая пару дней назад была daily challenge. Продублирую условие:
Given two positive integers num1 and num2, find the positive integer x such that:

x has the same number of set bits as num2, and
The value x XOR num1 is minimal.
Note that XOR is the bitwise XOR operation.

Return the integer x. The test cases are generated such that x is uniquely determined.

The number of set bits of an integer is the number of 1's in its binary representation.

И ограничения:
1 <= num1, num2 <= 10^9


Догадываюсь, что с первого взгляда кажется, что написана какая-то ерунда. Действительно: в этой задаче главное – понять условие правильно. По сути нам нужно "создать" новое число и в него поставить столько единичек, сколько их в num2. Это можно сделать многими способами, но у нас есть дополнительное условие: XOR-сумма с num1 должна быть минимальна. Как известно 1 XOR 1 = 0, 0 XOR 0 = 0, 1 XOR 0 = 1, 0 XOR 1 = 1, т.е. имеет смысл идти по битам числа num2 слева направо копируя их в результат (не забывая, что вообще говоря num2 может содержать больше битов, чем нам нужно). А если вдруг мы скопировали весь num2, но битов не хватает – не теряемся, просто заполняем пустые разряды res уже теперь справа налево.

Небольшое замечание перед тем, как я покажу код: вообще в C++, конечно, есть побитовые операторы, сдвиги и т.д., и, можно было реализовывать, опираясь только на них, но удобнее использовать bitset. И вторая ремарка: не вчитывайтесь – попытайтесь решить сами.

class Solution {
public:
constexpr static const int bin_size = 30;
using bits = bitset<bin_size>;

int minimizeXor(int num1, int num2) {
bits b1 = num1;
bits b2 = num2;
bits res = 0;

int count = b2.count();
auto index = bin_size - 1;

while (count && index >= 0)
{
if (b1[index])
{
res.set(index);
count--;
}

index--;
}

index = 0;

while (count)
{
if (!res[index])
{
res.set(index);
count--;
}

index++;
}

return res.to_ulong();
}
};

#today #c_plus_plus #leetcode #algo
👍1
Daily question

Не совсем понимаю почему, но второй день подряд вижу забавные задачки на XOR на Leetcode: условие в этот раз длинное – предлагаю прочесть его по ссылке самостоятельно.

Если вкратце: дано два, возможно довольно длинных, целочисленных массива, нужно найти XOR всех возможных пар. Т.е. если в первом массиве 10 элементов, во втором 11, то нужно найти XOR 110 пар – что было бы квадратичным (неэффективным) алгоритмом. Советую решить самим прежде чем читать спойлер и код.

Нам понадобится два свойства операции XOR: её коммутативность, и факт, что XOR-сумма любого числа с самим с собой равна нулю при чётном числе элементов и равна самому элементу при нечётном числе элементов. В гигантском XOR всех-всех пар друг с другом каждый элемент первого массива встретится столько раз, сколько элементов во втором массиве, и аналогично для второго массива. Иначе говоря, всё зависит только от чётности длин массива, и в худшем случае мы получим алгоритм линейный от совокупных длин массива, а в лучшем случае и вовсе – O(1).

class Solution {
public:
int xorAllNums(vector<int>& nums1, vector<int>& nums2)
{
int res = 0;

if (nums2.size() % 2 == 1)
{
for (const auto& x: nums1)
{
res ^= x;
}
}

if (nums1.size() % 2 == 1)
{
for (const auto& x: nums2)
{
res ^= x;
}
}

return res;
}
};


#today #c_plus_plus #leetcode #algo
👍1
Daily question, again

На Leetcode похоже ежемесячник смешных задач на XOR. Всё остальное сразу убираю под спойлер.

Итак, сразу понятно, что о каком-либо переборе всех возможных массивов original с пересчётом их deriverd речь идти не может – это было бы экспоненциальное время работы. Вместо этого внимательно посмотрите на Example 1: в расписанных формулах для элементов derived каждое значение original фигурирует ровно дважды – это значит, что XOR-сумма элементов валидного derived, полученного из произвольного original обязана быть равна нулю.

class Solution {
public:
bool doesValidArrayExist(vector<int>& derived) {
int res = 0;

for (const auto& x: derived)
{
res ^= x;
}

return res == 0;
}
};

#today #c_plus_plus #leetcode #algo
Хорош ли номер

Эта серия с Leetcode подзатянулась, но это не значит, что я её не продолжу:) Сегодня предлагаю просто почитать задачу уровня Hard, с удивительно низким для меня уровнем Acceptance порядка 20 процентов – решение я опубликую потом.

Сразу скажу: решение довольно простое, укладывающееся в сотню строк; причём достаточно использовать только сравнение символов, итерирование по строке и прочие низкоуровневые штуки, использовать тут regexp – неспортивно.

#today #c_plus_plus #leetcode #algo #ToBeContinued
👍1
Умер Дэвид Линч – режиссер многих картин, самой глубокой и яркой из которых, пожалуй, является сериал Твин Пикс.

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

Твин Пикс – шедевр, где эти две составляющие взаимообогащают друг друга, формируя целостное, многослойное кинополотно, поглощающее зрителя с первого эпизода. Путь Агента Купера до Чёрного вигвама – не банальное путешествие из точки А в точку Б, да и проходит он вовсе не в физическом мире...

#sorrow #books #movies
🔥2
Хорош ли номер ч. 2

Вернёмся к задаче из поста: решение я всё ещё придержу. Кстати, в данном случае использование конечных автоматов, предложенных тут в комментариях, в принципе оправдано, хотя – в своём решении я не использую их. Если кто-то из подписчиков реши(л|т), используя этот формализм, – предлагаю привести решение в комментариях.

Я же тут, пока что написал регулярное выражение подходящее под условие (\-\+)?((\d)+)|((\d*\.\d+)|(\d+\.\d*))((e|E)\d+)? – считайте это подсказкой.

#today #c_plus_plus #leetcode #algo #ToBeContinued
👍1
Обычно я не комментирую события такого рода в этом канале. Но этот случай – особенный. Нет на свете человека, кто знал бы наперёд, что ждёт мир, даже сам виновник новостей не может знать заранее какие свои планы он сможет реализовать и какие – нет.

Однако, хоть это и смутный и неверный, но шанс на улучшение ситуации. Не зря же давеча приснился мне сон, что я – там, на инаугурации Трампа; и все вокруг удивляются, что кругом снег, хотя откуда он, если его нет и в Москве? :)

В любом случае: дата 20.01.2025 историческая. Let's make something great again.

#today #news #history #USA #Trump
Хабр банит неугодных

На днях запретили публикации Антону Назарову, создателю канала «Осознанная меркантильность». Перед этим автору слили рейтинг и карму с помощью накрутки. Компаниям неприятно распространение идей, что найм можно взломать и «войти в айти», не имея должной квалификации, ведь работодатель теряет деньги, наняв «волка».

Несмотря на наши разногласия во взглядах на найм и этичность его взлома, затыкать рот кому-либо административными методами — это отвратительное проявление цензуры и произвола, которым не место в XXI веке.

Читать далее
👍1
Хорош ли номер ч. 3

Закончим задачу из поста.

Итак, в прошлый раз я уже писал regexp, теперь проговорю словами: по сути валидное число это decimal или integer, которые могут быть продолжены символом 'e' или 'E' за которым идёт integer. Очень читабельное решение получается при разбиении строки на две части – до и после 'e/E'. Полученные части будут достаточно просты, что б проверить их циклом в один проход.

Код будет в комментарии. Обратите внимание на функцию isDecimal: на самом деле она не отличает decimal от integer, но это работает:) – Да, углы немного срезаны. Итоговая сложность, очевидно, линейна.


#today #c_plus_plus #leetcode #algo
👍1
Обычно я пишу заметки в тот момент, когда у меня на руках уже есть готовое решение – возможно, оно сделано несколько лет назад, возможно – сегодня.

Однако, часто так бывает, что найти хорошее решение, не изобретая велосипед, – практически невозможно. Неожиданный пример такой проблемы: умножение двух uint64_t по модулю в C++. Тут важны все слова: умножить без модуля – не очень сложно, использовать uint32_t – легко, не в C++ – окей, кто знает – тот знает.

А в чём собственно проблема? – в том, что, вообще говоря, произведение двух uint64_t не влезет в uint64_t, а стандартного типа uint128_t – нет.

Но есть же какая-то библиотека, где это уже сделано? – конечно, тот же gmp, но это не то решение, которое я ищу.
А что, если разбить uint64_t на две половинки по 32 бита, как-то их перемножить и т.д.? – к сожалению, это тоже не работает, в какой-то момент в формуле всё равно вылезет необходимость перемножить два uint64_t. Есть пара похожих вариантов, которые мне лень расписывать, и которые тоже не работают.
А есть же расширение __int128? – Да, есть, но только для GCC.
И что ничего нельзя сделать, если хочется получить самописную платформонезависимую реализацию данной операции? – Можно, вот только потребует это удивительно много строк кода.

Рассмотрим пару вариантов:
1) реализовать сначала обычное умножение с сохранением в пару uint64_t, потом по-честному поделить на модуль, вернув остаток
2) использовать алгоритм Монтгомери

Относительно первого варианта: реализовать умножение – сравнительно легко, вот с делением будет проблема: стандартный алгоритм (примерно то, что изучается в школе) потребует явный цикл...есть другие алгоритмы, но они ещё более неприятны в имплементации (например, рассмотренный мной метод Ньютона-Рафсона)

Относительно второго варианта – он выходит за рамки среднестатистических знаний об алгоритмах (включая, и мои знания на данный момент), но вот вам ссылка.

Вишенка на этом торте безумной "удобности" C++ является то, что процессор это умеет: можно посмотреть тут. Можно в godbolt дизассемблерить простой листинг для GCC.
typedef unsigned __int128 uint128_t;
uint128_t mult(uint64_t a, uint64_t b)
{
return uint128_t(a) * uint128_t(b);
}

Так что вы говорите там будет интересного в новом стандарте?

#today #c_plus_plus #algo #hatred
👍2
Вернемся к задачам на Leetcode: часто такое бывает, что читаешь условие – и не можешь понять, что нужно сделать, перечитываешь снова, смотришь testcases, и только тогда – понимаешь. С этой сложной задачей всё абсолютно наоборот – сложно представить себе условие сформулированное ещё проще, тут даже разработчиком быть не обязательно.

Convert a non-negative integer num to its English words representation. То есть записать данное положительное целое число прописью.

Решение будет опубликовано спустя несколько дней. Кстати, на всякий случай уточню: задачи Leetcode не привязаны к определенному ЯП – просто на данный момент мне проще решить их на C++, но если вам более знаком Python, C#, you name it – просто используйте их, скорее всего платформа его поддерживает.

#leetcode #algo #ToBeContinued #English
👍1
Forwarded from Типичный программист
This media is not supported in your browser
VIEW IN TELEGRAM
На разных этапах карьеры — разные уровни спокойствия

#кек
😁3
Книги ч.2

Стиль и сюжет – не единственный способ рассуждения о книгах. Забавно, но можно увидеть аналогию между всем произведением и его малой составляющей – предложением. Как известно, приличное предложение должно состоять хотя бы из одной пары подлежащего и сказуемого, так вот – это и есть сюжет, а именно: подлежащее – главный герой (герои), сказуемое – его поступки. Карл/командор/принцесса родился/полетел/пошёл на войну, затем попал в Пентагон/ нашёл миллион/ познакомился – и так далее.

А ещё есть всякие второстепенные члены предложения: обстоятельства, определения, дополнения. Поскольку это аналогия, а любая аналогия – фаль^W^неточна – я укорочу этот список, так же как и содержание этих категорий. В данном контексте определение – лишь то, что характеризует главных героев, включая изначальную репрезентацию, а обстоятельство – всё что угодно их окружающее и являющееся фоном повествования, включая и повседневное толкование этого слова, дополнений же – не существует вовсе.

Итак, главный герой какой он там и откуда: отважный/сонный капитан дальнего плавания родом из Харбина, увлекающийся поэзией/квантовой физикой, – это всё его определение, которое может изменяться и/или развиваться в процессе повествования. Где и на каком фоне происходят события – в Париже начала 20-го века, в Средиземье, во сне – обстоятельство.

Возвращаясь к озвученному в прошлом посте: сюжет – последовательность действий главных героев (подлежащее и сказуемое), стиль – совокупность второстепенных членов предложения...Нет! Стиль – это метакатегория, это инструмент, которым создаётся всё повествование, но в тоже время, включающий в себя обстоятельства и определения.

Кстати, всё вышеизложенное я в шутку окрестил "Лингвистической теорией разбора". Не претендую на истину в последней инстанции.

#today #flood #superflood #books #humor
👍1
Продолжим то, что начали в прошлый раз.

Несмотря на простую, формулировку testcases пригодятся: язык хоть мне и знакомый, но не родной – редко приходится озвучивать числительные да и ещё такие большие.

Итак, для 1 234 567 нужно выдать "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven". Думаю довольно очевидно, что все уникальные числительные будут константами так или иначе организованными в листинге, а именно это числа 0-19, 20, 30...90, 100, 1000, 1000 000, 1000 000 000. Далее, по большей части я вынужден перефразировать подсказки данные в условии (честно скажу, что я прочёл их уже после успешного submit).

Рассмотрите отдельные тройки разрядов, обратите внимания, что их звучание однотипно – отличие только в том, что одна группа это Million, другая Thousand, ну а последняя (Ones) – суффикса не требует. Так же нам везёт, что все эти Million/Thousand сами не склоняются по числу ( не требует 's'). Внутри же этой тройки разрядов всё достаточно просто: озвучиваем первую значащую цифру, прибавляя Hundred, далее если в оставшихся двух разрядах число старше 19, то озвучиваем сначала десяток, потом вторую цифру, если число не старше 19 – озвучиваем сразу две цифры. И да – нули не озвучиваем.

Как выделяются тройки разрядов и обработку corner-cases – посмотрите в листинге или в подсказках на платформе. Листинг в комментарии к посту.


#leetcode #algo #c_plus_plus #English
👍1
Channel photo updated