Страницы

Поиск по вопросам

четверг, 20 декабря 2018 г.

Как отследить утечку памяти

Работаю под Visual Studio. Как узнать, есть ли в программе утечка памяти или нет?


Ответ

Возможно обнаружение утечек памяти с помощью отладчика и отладочных функций кучи библиотеки CRT (библиотеки времени выполнения). Включаются они так:
#define _CRTDBG_MAP_ALLOC #include #include
Важно, что инструкции include/define следуют в таком порядке.
Включение заголовочного файла сопоставляет функции malloc и free с их отладочными версиями: _malloc_dbg и free. Инструкция define позволит сделать дамп утечки памяти более подробным (вообще говоря, она сопоставляет базовые версии функций кучи CRT соответствующим отладочным версиям).
Далее помещаем вызов _CrtDumpMemoryLeaks перед точкой выхода приложения для отображения отчета об утечке памяти перед завершением работы приложения:
_CrtDumpMemoryLeaks();
Если точек выхода несколько, нет нужды писать вызов этой функции повсеместно. Достаточно вызвать в начале работы приложения функцию _CrtSetDbgFlag, что приведет к автоматическому вызову функции _CrtDumpMemoryLeaks в каждой точке выхода. Для этого надо установить значения двух битовых полей:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
По умолчанию _CrtDumpMemoryLeaks выводит отчет об утечке памяти в область Отладка окна Вывод
Далее смотрите полученные данные, там четко указывается тип блока, его расположение, размер утечки и еще некоторая информация. Блоки бывают разных типов (см. справку CRT).
Примечание: В некоторых случаях _CrtDumpMemoryLeaks может ошибочно диагностировать утечку памяти, но я не буду здесь расписывать данные ситуации, если потребуется или Вы не разберетесь самостоятельно - пишите комментарии;)

Не туда, куда надо добавляется класс

Здравствуйте.
Я еще учу jQuery. Сегодня столкнулся с проблемой, что не туда, куда надо добавляется класс. Нужно, чтобы новый класс был у

, а вышло у
$(function () { var elem = $('body'); elem .append('

Some text

')) .addClass('new'); }); .new { color: red; }
Заранее спасибо.


Ответ

.prependTo( "body" ); вам в помощь или .appendTo("body");
$(function() { $('

') .html('Some text') .addClass('new') .prependTo("body"); }); .new { color: red; }

Как определяется каталог поиска файла?

Есть такой код:
if(File.Exists("text.txt")) //работа с файлом
Вопрос в следующем: как определяется каталог в котором будет производится поиск указанного файла?
Как спровоцировать ситуацию, когда файл существует ( в случае с данным примером в каталоге откуда было запущено приложение ) но условие не выполнится?


Ответ

Если указан относительный путь к файлу, то поиск будет проходить относительно текущего каталога. (Получить или изменить его можно при помощи Environment.CurrentDirectory.)
Обычно при запуске программы текущий каталог наследуется от запускающей программы*. Это значит, что если вы запустите программу из командной строки, находясь в каталоге с программой, то текущий каталог программы будет совпадать с каталогом, где она расположена. Если вы запустите программу из другого каталога (всё равно, по относительному или по полному пути), каталог программы и её текущий каталог будут отличаться.
Также вы можете установить произвольный рабочий каталог через ярлык:

Ну и программа сама может поменять свой рабочий каталог в любой момент через уже упомянутое свойство Environment.CurrentDirectory

*Если в параметрах функции CreateProcess не указан необязательный параметр lpCurrentDirectory. Ну или для C# если в ProcessStartInfo не установлено свойство WorkingDirectory

Разные результаты при умножении больших чисел

Почему получается разный результат:
__int64 f1() { return 24 * 60 * 60 * 1000 * 1000; }
__int64 f2() { __int64 value = 24 * 60 * 60 * 1000; return value * 1000; }
int main() { __int64 value1 = f1(); //500654080 __int64 value2 = f2(); //86400000000 }


Ответ

Целочисленный литерал вроде 1000, 64 и т.п. имеет тип int и выражение с умножением этих чисел тоже имеет тип int. Итоговое значение не помещается в целовой тип (происходит переполнение, формально UB) и вы видите искаженные результаты. При сохранении промежуточного значения в более широкий тип, результат последующего умножения также будет иметь более широкий тип, который способен содержать итоговое произведение правильно.
Чтобы заработал первый вариант, достаточно добавить к одному из литералов суффикс ll, таким образом превратив литерал из типа int в тип long long int

FILE после открытия получает указатель 0x1

В main методе только вызов этой функции: add_entry("123.txt", "123", "some text"); После запуска создается файл и на строке fputs вылетает SIGSEGV. Через дебагер запускаю и узнаю, что у f указатель 0x1 после открытия файла.
void add_entry(char* file, char* id, char* entry) { FILE* f; if(f = fopen(file, "w+")!=NULL) { char* entry1 = calloc(strlen(entry)+strlen(id)+3, sizeof(char)); sprintf(entry1, "%s|%s
", id, entry); fputs(entry1, f); fclose(f); } }
В чем может быть проблема?


Ответ

Ну так
f = fopen(file, "w+")!=NULL
рассматривается компилятором как
f = (fopen(file, "w+")!=NULL)
так что все верно...
Пишите вот так:
(f = fopen(file, "w+"))!=NULL

Явный вызов конструктора для объекта

Как создать объект в динамической памяти используя malloc()? Нужно ведь явно вызывать конструктор, как это сделать?


Ответ

Вам нужен placement new.
Например, так:
void* place = malloc(sizeof(Object)); Object* o = new(place) Object();
Не забудьте в конце вызвать и деструктор вручную:
o->~Object();
и если нужно
free(place);
Документация: https://isocpp.org/wiki/faq/dtors#placement-new

Для случая, когда у вас память выделена заранее, вам придётся позаботиться о выравнивании. Обычный указатель, который возвращает malloc, имеет выравнивание, достаточное для нормально объявленного класса, то есть, класса, определение которого не содержит alignas() (а также определение классов его полей), и значит, ничего больше делать не нужно.
Если это (отсутствие alignas) не гарантировано, у вас есть два пути. Вы можете вместо malloc использовать aligned_alloc (или _aligned_malloc на старых версиях Visual Studio), который выдаёт malloc с нужным выравниванием:
void* place = std::aligned_alloc(alignof(Object), sizeof(Object)); void* place = _aligned_malloc(sizeof(Object), alignof(Object));
(да, порядок противоположный).
Или если вам нужен именно malloc, то можно заказать больше памяти для того, чтобы было место для выравнивания, и выровнять указатель при помощи std::align
std::size_t alloc_size = sizeof(Object) + alignof(Object) - 1; void* place = malloc(alloc_size); void* aligned_place = place; if (std::align(alignof(Object), sizeof(Object), aligned_place, alloc_size)) { Object* o = new(aligned_place) Object(); // ... }
Эта вторая техника пригодится, если вы захотите выделить в одном буфере несколько объектов.

Аналог нуль-коалесцирующего оператора в Питоне

def none_aware(val, default): return default if val is None else val
В библиотеке есть функция которая возвращает либо список либо None, а хочется написать
return [HtmlParser(el) for el in none_aware(content.select('...'), [])]
Вместо нескольких строк проверок.


Ответ

Можно попробовать так:
return [HtmlParser(el) for el in (content.select('...') or [])]
Нужно только учитывать что у класса может быть переопределён метод __bool__, но обычно даже в тех редких случаях, когда его переопределяют, его поведение в логических выражениях остаётся в рамках интуитивно ожидаемого.

Как обратиться к переменной внутри функции?

Есть такая функция, которая находит элемент на страницу, но когда я пытаюсь сделать что-либо с этим элементом, то консоль выдает:
$list.css is not a function
Как мне проводить манипуляции с этой переменной?
$(document).on('click', ".repair_item", function() { var $list = $(this).find(".repair_item_hiddenList_js").html(); $list.css('display', 'block'); }); .repair_item { width: 300px; height: 140px; margin-bottom: 30px; } .repair_item:hover { cursor: pointer; } .repair_item_flex { height: 100%; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; } .repair_item_img { width: 50%; height: 100%; } .repair_item_img img { width: 100%; height: 100%; } .repair_item_text { width: 50%; height: 100%; background-color: #37acfb; color: white; font-size: 15px; font-family: "Roboto Consendered Bold"; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; text-transform: uppercase; } .repair_item_hiddenList { display: none; background-color: #252525; width: 100%; color: white; padding: 25px 30px 20px; left: 0px; margin-top: 40px; } .repair_item_hiddenList_title { font-size: 17px; font-family: "Roboto Consendered Bold"; } .repair_item_hiddenList_list { list-style: none; padding-left: 0px; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; -ms-flex-wrap: wrap; flex-wrap: wrap; } .repair_item_hiddenList_list li { font-size: 15px; font-family: "Roboto Consendered Regular"; display: block; width: 270px; margin-bottom: 15px; } .repair_item_hiddenList_list li:before { content: "-"; position: relative; left: -10px; }

экран

Что мы можем сделать

  • Замена стекла
  • Ремонт дисплея после попадания влаги
  • Наклейка защитной пленки
  • Замена дисплейного модуля
  • Калибровка экрана
  • Выведение легких царапин и потертостей
  • Чистка дисплея от пыли
  • Наклейка защитного стекла
  • Диагностика

$(document).on('click', ".repair_item", function() { var $list = $(this).find(".repair_item_hiddenList_js").html(); $list.css('display', 'block'); });


Ответ

Вам нужно не block.html() добавлять .css, а самому блоку. Но, как я понимаю, не самому .repair_item_hiddenList_js, а его "ребенка" - .repair_item_hiddenList Вы хотите показывать, поэтому так:
$(document).on('click', ".repair_item", function() { var $list = $(this).find(".repair_item_hiddenList"); $list.css({'display': 'block'}); }); .repair_item { width: 300px; height: 140px; margin-bottom: 30px; } .repair_item:hover { cursor: pointer; } .repair_item_flex { height: 100%; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; } .repair_item_img { width: 50%; height: 100%; } .repair_item_img img { width: 100%; height: 100%; } .repair_item_text { width: 50%; height: 100%; background-color: #37acfb; color: white; font-size: 15px; font-family: "Roboto Consendered Bold"; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; text-transform: uppercase; } .repair_item_hiddenList { display: none; background-color: #252525; width: 100%; color: white; padding: 25px 30px 20px; left: 0px; margin-top: 40px; } .repair_item_hiddenList_title { font-size: 17px; font-family: "Roboto Consendered Bold"; } .repair_item_hiddenList_list { list-style: none; padding-left: 0px; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; -ms-flex-wrap: wrap; flex-wrap: wrap; } .repair_item_hiddenList_list li { font-size: 15px; font-family: "Roboto Consendered Regular"; display: block; width: 270px; margin-bottom: 15px; } .repair_item_hiddenList_list li:before { content: "-"; position: relative; left: -10px; }

экран

Что мы можем сделать

  • Замена стекла
  • Ремонт дисплея после попадания влаги
  • Наклейка защитной пленки
  • Замена дисплейного модуля
  • Калибровка экрана
  • Выведение легких царапин и потертостей
  • Чистка дисплея от пыли
  • Наклейка защитного стекла
  • Диагностика

тип Counter() - словарь или множество?

В описании типа Counter сказано что он - наследник dict. И не сказано, что он также и множество. Приведенный ниже код работает и выдает результат: Counter({'q': 1, 'w': 1})
from collections import Counter c1 = Counter({'q':1, "w":2}) c2 = Counter({'q':1, "w":1}) c = c1 & c2 print(c)
Вопрос - почему не описано, что он - множество? Или он "не вполне" множество?


Ответ

Это объект типа Counter (наследник dict) для которого перегружен оператор & (__and__(...))
def __and__(self, other): ''' Intersection is the minimum of corresponding counts. >>> Counter('abbb') & Counter('bcc') Counter({'b': 1}) ''' if not isinstance(other, Counter): return NotImplemented result = Counter() for elem, count in self.items(): other_count = other[elem] newcount = count if count < other_count else other_count if newcount > 0: result[elem] = newcount return result
Примеры:
In [54]: issubclass(Counter, dict) Out[54]: True
In [55]: issubclass(Counter, set) Out[55]: False
In [39]: type(c) Out[39]: collections.Counter
In [40]: c.items() Out[40]: dict_items([('q', 1), ('w', 1)])
In [41]: type(c.items()) Out[41]: dict_items
In [42]: c.keys() Out[42]: dict_keys(['q', 'w'])

Количество значений класса ENUM

Есть некий ENUM класс вида:
public enum Numbers { ONE = 1, TWO = 2, THREE = 3, FOUR = 4, FIVE = 5 }
Как узнать количество значений в списке перечисления? Просьба hardcode не предлагать.
P.S. В Java я могу взять весь список массивом и после узнать размер массива. Всё делается одной строчкой. Пример:
Numbers.values().length;
В Шарпе ума не приложу.


Ответ

Попробуйте так:
var enumCount = Enum.GetNames(typeof(Numbers)).Length;

Как масштабировать размеры иконок svg

Вот есть код:


При размерах 256 пикселей размер svg иконки не 256 пикселей, а где-то ~140 При указании 128, тоже не 128 и т.д. Почему так происходит? Я уже перечитал все эти мануалы, в примерах их иконки все нормально отображаются с размерами, а почему эта не работает как надо?!


Ответ

Интересный вопрос!
В вашем примере затронута одна из фундаментальных тем SVG - масштабирование. Поймете, как это работает и в svg будет всё легко и просто.
Масштаб определяется соотношением viewport / viewBox, где viewport это width="X" height="Y"
В вашем примере масштабирование применяется последовательно несколько раз. Очень легко запутаться. Поэтому я максимально упрощу ваш пример и поэтапно буду усложнять до практического применения
Ниже пример, где применяется масштабирование только один раз в шапке svg файла
viewport / viewBox = 100/100=1. Масштаб будет - 1:1 То есть как нарисовано в векторном редакторе, так и будет отражаться на дисплее

На скрине векторного редактора видно, что физически иконка имеет габариты - 56.6 х 56.6px
Теперь запускаем этот же файл в браузере. И для наглядности я добавил красный прямоугольник, через стили в шапке файла, который показывает границы SVG файла.
style="border:1px solid red;"

Границы svg определяет viewport это - width="100" height="100"
Из примеров видно, что иконка 56 х 56px не полностью занимает viewport - 100 х 100px
Это очень плохо, так как эти свободные пространства добавляют отступы от других элементов верстки HTML
Убираем лишние отступы
Для этого уменьшаем viewport до размеров иконки
width="56" height="56" viewBox="0 0 58 58"
Смотрим результаты в векторном редакторе и в браузере:

Пример в браузере

Масштабирование иконок до требуемых размеров
Размер 256 x 256px
Для этого увеличиваем размер viewport до требуемых размеров
Проверяем в векторном редакторе

Проверяем в браузере

Размер 128 x 128px
проверяем в векторном редакторе

Делаем рабочую версию приложения
Основное правило последовательных масштабирований в одном файле SVG
В шапке файла SVG задается самый большой viewport - это прямоугольная область, которую видит пользователь на экране. Если задали width="256" height="256", то последующие масштабирования, которые идут в коде ниже могут только уменьшать размер этой области.
Пример с 3 иконками 256x256; 128x128; 64x64
.alignlef { display: inline; float: left; margin-right: 1.625em; } path { fill:inherit; stroke:inherit; }


Группа администраторов в Ubuntu

Какая группа отвечает за группу администраторов в Ubuntu? В файле /etc/group есть группа "adm" и есть группа "sudo". Так вот, если назначить пользователя администратором, то этот пользователь добавится к группе "adm" и "sudo". Но если убрать права администратора у этого пользователя и сделать его обычным, то он удалится только из группы "sudo", но останется в группе "adm". Непонятно какая группа за что отвечает.


Ответ

Группа adm отвечает за доступ к некоторым логам в /var/log
# посмотрим на типичный лог файл ls -la /var/log/dmesg # ответ: -rw-r----- 1 root adm 58692 марта 17 12:24 /var/log/dmesg # посмотрим группы сислога: groups syslog # ответ: syslog : syslog adm
Группа sudo разрешает запускать с правами суперпользователя - это механизм, чтобы не работать под рутом. sudo можно настроить:
sudo cat /etc/sudoers # User privilege specification root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges %admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command %sudo ALL=(ALL:ALL) ALL
Таким образом, в sudo прописано, что root, и пользователи групп admin и sudo имеют супер привилегии. Группа admin появилась исторически, и оставлена для обратной совместимости. У меня на 14 убунте группы нет, но в sudoers она упоминается.
Для редактирования этого файла нужно ввести sudo visudo
Какая группа отвечает за группу администраторов?
При установке системы с нуля "админы" - это те, кто входит в sudo. А затем - как настроите.
Подробности
Нет понятия "система отличает админа от обычного юзера". Система более гибкая, все правила изложены в файле sudoers
Суперадмин root по-умолчанию в Убунте отключен. При установке создается пользователь, который включен в группу sudo, и через sudo {команда} может выполнять любые административные задачи.
Но затем sudo можно настроить так, что любой пользователь сможет выполнять любые, даже административные действия. И даже снести систему. И для этого не нужно включать пользователя в какую-то группу, достаточно "как надо" настроить файл sudoers
Пример. Мне нужно перезагружать Sphinx из веб-интерфейса, но я не хочу давать абсолютно все права веб-серверу (это не безопасно). Через sudoers я могу это сделать.
Резюме
Сначала следует проанализировать файл sudoers, понять как распределены роли, и тогда придет понимаение "кто тут админ".
Также выполните
awk -F: '($3 == "0") {print}' /etc/passwd
должна быть только 1 учетная запись с UID = 0, это root

кнопка - блок или ссылка?


Как лучше реализовывать такую кнопку?
Первый вариант:
div { width: 150px; text-align: center; background-color: #fff; border: 2px solid #ddd; } a { display: inline-block; padding: 3px 0; width: inherit; text-decoration: none; text-transform: uppercase; color: red; }


Или же второй вариант:
a { display: block; width: 150px; padding: 3px 0; text-decoration: none; text-align: center; text-transform: uppercase; color: red; border: 2px solid #ddd; load more


Ответ

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

Как укоротить код с обнулением возвращаемого значения?

Стало интересно, можно ли заменить данный код как то покороче? без использования временной переменной Мне нужно по возвращению значения "сбрасывать" его же
private static int a; a = ...; public static int foo() { int t = a; a = 0; return t; }
Вопрос из разряда "как поменять числа местами без использования мат.операторов"


Ответ

Не думаю что имеет смысл делать подобные "оптимизации", но можно еще так поизвращаться:
public static int foo() { try { return a; } finally { a = 0; } }

CSS. Измененить цвет при нажатии и сохранить изменённое значение

/* Элемент меняет цвет при наведении на него */ button.yt-icon-button:hover { vertical-align: middle; color: #ff0087; }
/* Элемент меняет цвет во время нажатия на доли секунд. */ button.yt-icon-button:active { vertical-align: middle; color: #01a715;
/* Элемент меняет цвет после нажатия, но стоит потом куда-то кликнуть и изменённый цвет заменяется на цвет по умолчанию. */ button.yt-icon-button:focus { vertical-align: middle; color: #01a715; }
Как сделать так, чтобы при клике изменялся цвет элемента и не изменялся на дефолт при клике на другое место.

Попробовала добавить код от Vadizar.
Получается вот так:

Но когда я добавляю нижнее, так как мне не нужно изменение фона. Я с фоном не работаю :
button { color: #ff9000 !important; transition: color 9999999s }
button:active { color: green; transition: color 0s }
у меня "палец вверх" не становится зелёным. Почему ?
И ещё:
Почему подсветка кода от Vadizar такая:

слово background выделяется зелёным
А при моём (скорей всего неправильном) варианте такая:

слово color не выделяется зелёным
И почему в конец после transition не добавляется ?


Ответ

Решение на чистом CSS без хаков с input: button { color: #fff; background: #000; padding: 1.2rem 2rem; cursor: pointer; user-select: none; border: none; outline: none; transition: background 9999999s; } button:active { background: red; transition: background 0s; }
Я не настаиваю на том, что это верный подход, и полностью согласен с решением St1myL. Тем не менее, данный пример показывает, на что способен CSS при извращенном воображении и может быть полезен в некоторых случаях, когда невозможно использовать JS и не подходит метод с input

Эстетичное форматирование json файла

Я использую библиотеку Gson для сериализации в json. Делаю я примерно вот так:
new Gson().toJson(new MyObject());
Но при этом у меня получается одна единая строка, без отступов и переносов:
{"classes":[{"name":"warrior","skills":[]}]}
Каким образом можно форматировать эту строку в более эстетичный вид, при сериализации, что бы потом можно было удобно менять значения? Та строка должна быть примерно такая:
{ "classes": [ { "name": "warrior", "skills": [] } ] }


Ответ

Добавьте настройку в билдер, а не просто создавайте инстанс Gson через конструктор:
Gson gson = new GsonBuilder().setPrettyPrinting().create(); String json = gson.toJson(new MyObject());

2 Enum с одинаковыми полями

Каким образом определить 2 enum с одинаковыми полями?
enum horizontal_alignment { stretch = 0x0, center, left, right };
enum vertical_alignment { stretch = 0x0, center, top, bottom };


Ответ

Либо спрятать каждый enum в отдельный namespace или класс.
Либо использовать scoped enum
enum class horizontal_alignment { stretch = 0x0, center, left, right };
enum class vertical_alignment { stretch = 0x0, center, top, bottom };
Разумеется, обращаться к элементам таких enum придется с указанием полного имени vertical_alignment::stretch

Задача с доской

Имеем доску, в которую на определенном расстоянии друг от друга вбиты гвозди. Любые два гвоздя можно соединить веревкой. Надо соединить веревкой некоторые пары гвоздей так, чтобы к каждому гвоздю была привязана веревка, а расстояние между гвоздями было минимальным. Вводные данные: дано целое число N — количество гвоздей (2 ≤ N ≤ 100). На другой строчке даны N чисел — координаты гвоздей (разные, неотрицательные числа, которые не превышают 10000). Вывод: Вывести минимально возможную длину всех веревок. Примеры Ввода/Вывода:
+------------------+-------------------+ | стандартный ввод | стандартный вывод | +------------------+-------------------+ | 6 | 5 | | 3 4 12 6 14 13 | | +------------------+-------------------+ | 7 | 5 | | 3 2 1 4 5 7 9 | | +------------------+-------------------+
Мой код:
#include #include #include
using namespace std;
int n, sk[10000], min[10000], not[10000], tot; int ats=0;
int main() {
cin >> n; for(int i=0;i> sk[i]; } for(int a=0;a } else { min[y]=abs(sk[y]-sk[e]); tot=e; } } } } for(int l=0;l

Ответ

Ясно, что соединять веревкой имеет смысл только соседние гвозди (после сортировки расположения гвоздей).
На самом деле - ну их нафиг, эти паросочетания (см. ниже). Прав @Igor - рекурсия (с мемоизацией) тут будет в самый раз.
Ясно, что первый и последний промежуток между гвоздями надо связывать обязательно. Если второй промежуток не связывать, то третий - надо связывать обязательно. Если второй промежуток связывать, то третий - нельзя связывать, а четвертый - надо связывать обязательно.
Получаем схему рекурсивного перебора:
связывать - не связывать - (рекурсивный вызов) связывать - связывать - не связывать - (рекурсивный вызов)
(Опять же - это полностью соответствует ответу @Igor.)
На С++
#include #include #include #include #include #include
using Weight = unsigned; using Weights = std::vector;
Weight min_sum(const Weights &weights, size_t i = 0) { assert(i < weights.size()); size_t n = weights.size() - i;
if (n == 1) return weights[i]; else if (n == 2) return weights[i] + weights[i + 1]; else if (n == 3) return weights[i] + weights[i + 2]; else return std::min( weights[i] + min_sum(weights, i + 2), weights[i] + weights[i + 1] + min_sum(weights, i + 3)); }
int main() { std::vector nails; std::copy(std::istream_iterator(std::cin), std::istream_iterator(), std::back_inserter(nails)); std::sort(nails.begin(), nails.end()); std::copy(nails.begin(), nails.end(), std::ostream_iterator(std::cout, " ")); std::cout << std::endl;
Weights weights; std::adjacent_difference(nails.begin(), nails.end(), std::back_inserter(weights)); weights.erase(weights.begin()); std::copy(weights.begin(), weights.end(), std::ostream_iterator(std::cout, " ")); std::cout << std::endl;
std::cout << min_sum(weights) << std::endl; }
http://coliru.stacked-crooked.com/a/13244f823d44f93d
Имеет смысл добавить мемоизацию по i, ибо возникновение одинаковых подзадач - возможно.

Непереборный подход:
Задача является задачей поиска реберного покрытия минимального веса в "зигзагообразном" двудольном графе (одна доля - четные гвозди, другая - нечетные, вес ребра W(u,v) равен расстоянию между гвоздями). Возможно (и даже скорее всего), это чересчур общий подход, т.е. "стрельба из пушки по воробъям", ибо граф имеет очень простую структуру, но пока закроем на это глаза.
Далее следуем предложенному самим Дэвидом Эппстейном вот здесь подходу. Ясно, что комбинации из трех последовательных ребер не имеют смысла - среднее ребро в такой комбинации является лишним. Тогда любое решение можно представить в виде некоего паросочетания M в исходном графе, плюс возможно несколько дополнительных ребер, предназначенных для присоединения непокрытых паросочетанием M вершин. Ясно, что непокрытые паросочетанием M вершины надо присоединять к M через ребра минимального веса, выходящие из таких вершин.
Пусть C(v) - это веc самого короткого ребра, выходящего из вершины v. Тогда вес решения, определяемого паросочетанием M, можно записать как
Σ C(v) - Σ С(u) + C(v) − W(u,v) | | по всем v по всем (u,v) из M
Первая Σ не зависит от M. Поэтому, чтобы минимизировать вес решения, нам надо максимизировать вторую Σ. А это - задача о паросочетании максимального веса в том же самом двудольном графе, но с весами ребер
W'(u, v) = С(u) + C(v) − W(u,v)
Задача, возможно, упрощается "зигзагообразностью" двудольного графа. Задача, возможно, усложняется наличием отрицательных весов.
Осталось только решить задачу о паросочетании максимального веса в таком графе ))) (Хотя, как справедливо заметил в комментариях @Fat-Zer, задача интуитивно не выглядит более простой, чем исходная)

Например
1.
Гвозди 3 4 6 12 13 14 W 1 2 6 1 1 С(v) 1 1 2 1 1 1 W' 1 1 -3 1 1
Максимальное паросочетание M (одно из возможных): 3-4, 12-13 Добавляем непокрытые вершины ребрами минимальной длины:
3-4-6 12-13-14
Вес: 5
2.
Гвозди 1 2 3 4 5 7 9 W 1 1 1 1 2 2 С(v) 1 1 1 1 1 2 2 W' 1 1 1 1 1 2
Максимальное паросочетание M (одно из возможных): 2-3, 4-5, 7-9 Добавляем непокрытые вершины ребрами минимальной длины:
1-2-3 4-5 7-9
Вес: 5
3.
Гвозди 1 2 5 9 11 12 W 1 3 4 2 1 С(v) 1 1 3 2 1 1 W' 1 1 1 1 1
Максимальное паросочетание M: 1-2, 5-9, 11-12 Добавлять нечего.
Вес: 6

Что такое trap representation?

В комментариях к ответам на этот вопрос. Был упомянут термин «trap representation»:
«Даже при использовании дополнительного кода реализациям разрешается резервировать значение −263 в качестве trap representation. Поэтому формально представимость −263 — не гарантируется даже в дополнительном коде» (@AnT).
Что это такое?
P. S. Я нашел ответ на enSO, но там, понятное дело, на английском.


Ответ

Trap representation - это комбинация байтов в объектном представлении какого-либо типа T, которая не обязательно является корректным представлением какого-либо значения типа T. Попытка работы с таким представлением как со значением типа T приводит к неопределенному поведению.
Предпосылок, из-за которых в представлении типа могут существовать trap representations существует много разных. Не претендуя на полноту:
Нетривиальная структура объектного представления типа
Нетривиальная структура внутреннего представления обычно ведет к возникновению внутренних инвариантов, нарушение которых порождает trap representation. Например, объектное представление даже простейших типов может содержать биты четности, предназначенные для проверки целостности данных. Значение, в котором нарушены инварианты четности, задаваемые этими битами - это trap representation.
Нетривиальная структура внутреннего представления также приводит к том, что часть объектных представлений натуральным образом получаются просто "ненужными", бессмысленными. Они являются прямыми кандидатами на trap representations. Например, среди представлений значений плавающих типов IEEE 754 есть комбинации битов, которые являются представлениями signaling NaN ("Not-a-Number" - "не число"). При соответствующей конфигурации FPU попытка работы с такими значениями будет мгновенно приводить к исключению. Это тоже классический пример trap representation. Специально зарезервированные значения
Реализации имеют право по своему усмотрению отказываться работать с некоторыми, на первый взгляд "невинными" представлениями достаточно тривиальных типов. Например, платформы, использующие для представления отрицательных целых чисел прямой (signed magnitude) или обратный (1's-complement) код, имеют право отказываться работать с представлением "отрицательного нуля", рассматривая его как trap representation. Платформы, использующие дополнительный код, имеют право рассматривать битовое представление 100...0 как trap representation. Представления, корректность которых зависит от внешних факторов
В этих случаях trap representations не являются заранее фиксированными. Например, значения указателей, которые не указывают на доступную программе память, могут рассматриваться платформой как trap representations, т.е. вызывать неопределенное поведение уже при обращении к такому значению указателя, еще до того, как мы попытаемся обратиться к самой памяти. Например, на платформе с сегментной организацией памяти уже сама попытка загрузки в сегментный регистр неправильного значения дескриптора сегмента может вызывать падение программы. Совершенно аналогичным образом как trap representation могут рассматриваться значения разнообразных тесно интегрированных в платформу хэндлов, дескрипторов и т.п. Намеренная симуляция trap representation для отладочных целей
Многие современные реализации предоставляют средства "санитизации" отладочной версии кода. Например, попытка чтения значения неинициализированной переменной может приводить в немедленному прерыванию программы с выдачей диагностического сообщения. Это поведение - пример искусственно и намеренно созданного trap representation на уровне software.
В то же время некоторые аппаратные архитектуры поддерживают аналогичную функциональность на аппаратном уровне. Например, архитектура Itanium поддерживает специальное состояние аппаратных регистров - NaT ("not-a-thing", "ничто"), которое соответствует именно trap represеntation в терминологии языка. (Это состояние предназначено в первую очередь для обозначения неинициализированности регистра.)
Единственным фундаментальным объектным представлением, для которого гарантируется отсутствие trap representations, является представление значений типа unsigned char (и типа char в реализациях, где char является беззнаковым типом). Благодаря этому любые объекты можно переинтерпретировать как массивы unsigned char [] и смело просматривать содержимое таких массивов, не боясь наткнуться на trap representation.
Представление объекта типа struct или union никогда не считается trap representation, даже если одно из его полей содержит trap representation. Т.е. чтение содержимого такого struct/union объекта как с единого целого не приводит к неопределенному поведению, в то время как чтение конкретного поля, содержащего trap representation - приводит.

P.S. На связанную тему:
В стандарте С89/90 чтение неинициализированного значения всегда приводило к неопределенному поведению. В стандарте С99 эта часть спецификации изменилась: в С99 неинициализированная переменная теперь содержит либо неспецифицированное значение, либо trap representation. В случае trap representation возникает неопределенное поведение, а вот в случае неспецифицированного значения неопределенного поведения не возникает. Как сказано выше, тип unsigned char не имеет trap representations. То есть получилось так, что в С99 чтение неинициализированного значения типа unsigned char просто дает неспецифицированное значение и гарантированно не вызывает неопределенного поведения.
Это, однако, идет вразрез с изначальными намерениями авторов стандарта.
Во-первых, требование того, чтобы тип unsigned char не имел trap representations, было введено для того, чтобы через массивы unsigned char [] можно было просматривать "бинарное" содержимое других объектов в памяти, а отнюдь не для того, чтобы переменные типа unsigned char можно было "забывать" инициализировать.
Во-вторых, это создало проблемы с архитектурой Itanium и ее NaT: если реализация для платформы Itanium захочет хранить локальную переменную типа unsigned char в регистре, то этим реализациям придется насильно инициализировать такие регистры, чтобы вывести их из состояния NaT, что идет вразрез с традиционно принятым в С подходом.
В конечном итоге было решено еще дополнительно подправить спецификацию языка в версии С11 (раздел 6.3.2.1/2): если вся работа с локальной переменной в коде соответствует требованиям класса хранения register (т.е. переменная потенциально может храниться в регистре), то чтение неинициализированного значения такой переменной однозначно приводит к неопределенному поведению. Это касается как неинициализированных переменных типа unsigned char так и неинициализированных переменных типа struct
В частности, эта часть спецификации иллюстрируется довольно странными примерами
void foo() { unsigned char junk; unsigned char a = junk + 1; // неопределенное поведение
struct { int i; } a, b; a = b; // неопределенное поведение }
void bar() { unsigned char junk; &junk; unsigned char a = junk + 1; // неспецифицированное значение
struct { int i; } a, b; &b; a = b; // неспецифицированное значение }

Заполнение таблицы БД с помощью словарей с ключами равными именам колонок

Есть список словарей вида:
[{"1":"1","2":"1"},...]
в котором ключи словарей являются колонками в таблице БД. То есть, все словари с одинаковыми ключами, но с разными значениями. Мне надо добавить эти значения в таблицу.
Как это реализовать?


Ответ

Можно воспользоваться модулем Pandas
import pandas as pd from sqlalchemy import create_engine
data = [{'a':1, 'b':'string1'}, {'a':2, 'b':'string2'}, {'a':3, 'b':'string3'}]
# create SQL Alchemy DB connection # conn = create_engine('postgresql://user:password@host:port/dbname') conn = create_engine('postgresql+psycopg2://user:password@host:port/dbname')
# create Pandas DataFrame from the list of records df = pd.DataFrame(data)
# write DF into SQL table df.to_sql('table_name', conn, if_exists='replace', index=False)
Пример DataFrame:
In [74]: df Out[74]: a b 0 1 string1 1 2 string2 2 3 string3

Java поиск строк в файле по ключевому слову

Есть лог файл в текстовом формате, весом 4gb. Структура файла - это N строк весом примерно 200 байт. Необходимо получать строки (добавлять их в массив), в которых есть ключевое слово. Очень важна скорость получения информации. На данный момент реализовано следующим образом:
public List readFileByFilter(String fileName, String filter) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(fileName)); ArrayList list = new ArrayList<>(); while (reader.ready()) { String tmp = reader.readLine(); if (tmp.matches(".*"+ filter +".*")) { list.add(tmp); } } reader.close(); return list; }
Подскажите, есть ли возможность сделать производительней (быстрей) данный участок кода?


Ответ

Строка
if (tmp.matches(".*"+ filter +".*")) {
вызываемая в цикле, это уникальнейший провал производительности
На каждой итерации цикла конструируется новая строка Используется регулярное выражение вместо простого поиска по тексту
Замените эту строку на
if (tmp.contains(filter)) {

Использование this в методах классов

Есть вот такой код:
template struct somestruct { ...
T somefunction(somestruct* const th = this) { return th ? th->somefield1 : this->somefield2; }
... };
Компилятор VS 2017 ругается:
Ошибка C2355 "this": может указываться только в нестатических членах-функциях или инициализаторах нестатических членов данных
Объясните пожалуйста, почему я не могу подобным образом использовать this?
Я хотел бы, чтобы вызов somepointer->somefunction(otherpointer) возвращал поле объекта указателя из аргумента, если он не nullptr, иначе возвращал другое поле объекта указателя, вызвавшего метод. А если somefunction вызывается без аргументов, то это было бы аналогично вызову somepointer->somefunction(somepointer). Конечно, можно делать такой вызов явно или просто перегрузить somefunction, но интересно, почему нельзя так, как я написал.


Ответ

Короткий ответ: потому что в стандарте языка сказано, что так нельзя.
Длинный ответ: в языке С++ не допускается формирование значений аргументов по умолчанию на основе параметров функции.
void foo(int a, int b, int c = a + b) // Ошибка { ... }
this - это тоже неявный параметр нестатического метода класса, поэтому использовать его для формирования значения аргумента по умолчанию не дозволяется. Причина этого заключается, в частности, в том, что это привело бы в необходимости вычислять параметры функции в некотором "правильном" порядке, а язык С++ не упорядочивает и никогда не упорядочивал вычисление параметров.† Это может быть не единственной причиной такого запрета.
Вместо аргумента по умолчанию вы можете просто использовать перегрузку и получить требуемый эффект
template struct somestruct { ...
T somefunction(somestruct* const th) { return th ? th->somefield1 : this->somefield2; }
T somefunction() { return somefunction(this); }
... };

† Начиная с С++17 вычисление аргумента для неявного параметра this упорядочено перед вычислением всех остальных аргументов. Теоретически, это должно было бы устранить вышеописанную проблему с порядком вычисления, но пока что это не привело к изменениям в спецификации использования this в аргументах по умолчанию.

Первичная установка или обновление андроид-приложения, как узнать программно?

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


Ответ

Есть такой подход - регистрируем ресивер на переустановку своего приложения:


public class MyAppUpdatedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // этот код будет выполнен после каждой переустановки // но при первой установке не вызывается } }
Другой вариант: записываем куда-нибудь номер версии и при каждом старте сравниваем с текущим, если изменился - выводим ченжлог

Подсчет площади трапеции из элементов массива

Имеется многомерный массив:
$arr = array( array( 'a' => 11, 'b' => 14, 'c' => 19), array( 'a' => 15, 'b' => 18, 'c' => 21), array( 'a' => 14, 'b' => 12, 'c' => 23) );
Как вывести три площади трапеции по формуле $s = 1/2 * $c *($a + $b); ? И требуется занести эти значения в новый массив?


Ответ

Как вариант можно использовать функцию extract
foreach ($array as $item) { extract($item); $stack [] = 1/2 * $c * ($a + $b); }
print_r($stack);

Очистка кэша apt-get

Как правильно удалить закачанные архивы пакетов apt-get? Я посмотрел в папку /var/cache/apt/archives и нашел там список пакетов *.deb, можно их просто удалить, но непонятно, правильно ли это.


Ответ

Для очистки локального кэша пакетов используется apt-get с командой clean: sudo apt-get clean Подробнее - в man apt-get

Как передать в C# массив строк из неуправляемой библиотеки?

Привет! Функция на C в DLL (которую я не могу менять), возвращает массив строк. Число элементов массива заранее неизвестно и может быть от 0 до 255. #define MAX_ARRAY_SIZE 255
// // Возвращает длину массива (количество строк) // LONG GetStringArray(char **Array); Реально ли вообще передать такие данные через P/Invoke? Если да, то как подступиться к задаче?


Ответ

Самый удобный способ это по совету wow использовать Managed C++ и написать обертку оттуда. Можно и сделать чуть более криво примерно так(я добавил ссылку на входной массив, чтобы не использовать внешнюю функцию инициализации, которая необходима при вашем описании GetStringArray ) как: С++ extern "C" __declspec(dllexport) LONG StringFunc(char** &data);
LONG StringFunc(char** & data) { LONG count = 2; data = new char*[count]; data[0] = new char[10]; data[1] = new char[10]; strcpy(data[0], "str1"); strcpy(data[1], "bla bla1"); return count;
} С#: [DllImport(@"..\..\..\..\debug\NativeDll.dll")]
public static extern LONG StringFunc(ref IntPtr data);
public static String[] CallNative() { IntPtr ptr_start = IntPtr.Zero; LONG count = StringFunc(ref ptr_start);
//массив указателей на строки IntPtr []ptr_strings = new IntPtr[count]; //копируем указатели на строки Marshal.Copy(ptr_start, ptr_strings, 0, count); String[] strings = new string[count];
for (int i=0;i< count; i++) { strings[i] = Marshal.PtrToStringAnsi(ptr_strings[i]); }
return strings; }
static void Main(string[] args) { String[] strings = CallNative(); Array.ForEach(strings, s => Console.WriteLine(s)); }

nil в языках программирования

Меня интересует как используется nil в различных языках программирования, и вообще насколько это удобно с точки зрения дизайна языка. В данной теме обсуждаются исключительно динамически типизированные языки. К примеру в JavaScript есть два значения похожих на nil: null и undefined. (Нужно ли было плодить?) В Scheme есть #f, но нет nil. В Factor тоже нету nil, и используют f. (Нужен ли nil если есть false?) Кроме того, как-то читал что вроде в первых версиях Objective-C был объект nil (Objective-C не знаю вообще), который поглощал вызовы, был чёрной дырой. Т.е. вёл себя как NaN для чисел. На любое сообщение объект возвращал nil Насколько допустимо трактовать "пустые" объекты (пустой список, пустой словарь и т.д.) как false, и есть ли у такой фичи опасные побочные эффекты, или вообще расположение к каким-либо багам. Приветствуются: Ссылки на статьи с обзором различных подходов Ссылки на какие-либо интересные языки, относящиеся к теме Обсуждение различных подходов, удобства и опасности использования


Ответ

NULL нужен там, где есть ссылки. Почему в JavaScript есть еще undefined? Потому что null и undefined - разные объекты. По умолчанию ссылка указывает на undefined, а null - элемент логики. Сейчас ссылка null, потом не null. Скажем так, в С/С++ указатели тоже не null изначально, а undefined. Пустые объекты - не false, потому что false - семантическое значение. Элемент логических выражений, а null - нет (несмотря на то, что он используется в них, он преобразовывается). Если кратко, то наличие пустого объекта обязательно для языков со ссылками, а false - это отдельный объект, такой же как строка "ABC" или 4 - т.е. непустой, а семантически значимый.

Производительность массивов

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


Ответ

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

Redim Preserve. Вопрос сложней, чем вы думаете.

Соответственно на C++ имеем класс: Class MyClass{ public: double *ptr; void Set(); }; MyClass::Set(){ ptr=new double[10000000]; } Далее в основном коде: MyClass *A; A=new MyClass[10000]; Затем требуется изменить размерность массива A с сохранением его элементов, вопрос в том как это сделать максимально производительно !?


Ответ

Способ в лоб: создать новый массив, скопировать туда элементы старого массива, уничтожить старый массив. Правильный способ: использовать STL. P.S. В таком классе, где происходит динамическое выделение памяти, нужно позаботиться об уничтожении ее в деструкторе и о копировании ее в копирующем конструкторе и в операторе присвоения. Иначе дело может очень плохо закончиться ((( PPS. Вот тут на досуге накропал нечто. Приятного аппетита. #include #include using namespace std;
enum {SIZE = 10000, SIZE_CL = 5};
class MyClass { private: double* ptr;
void array_cpy (MyClass& mc) { if (!flag) { cout << "Copying array" << endl; ptr = new double [SIZE]; memcpy (ptr, mc.ptr, SIZE*sizeof(double)); } else { cout << "Copying ptr" << endl; ptr = mc.ptr; mc.ptr = 0; } }
public: static bool flag ; static int count;
void set() { cout << "Creating array" << endl; ptr = new double [SIZE]; for (int i = 0; i< SIZE; i++) { ptr[i] = count; } count++; }
double get(int index) { return ptr [index]; }
MyClass (): ptr(0) {}
MyClass (MyClass& mc) { array_cpy(mc); }
MyClass& operator= (MyClass& mc) { array_cpy(mc); return *this; }
~MyClass () { if (!flag && ptr) { cout << "Deleting array" << endl; delete[] ptr; } } };
bool MyClass:: flag = false; int MyClass:: count = 0;
int main() { MyClass* aa = new MyClass [SIZE_CL]; for (int i = 0; i < SIZE_CL; i++) aa[i].set(); MyClass::flag = true; MyClass* bb = new MyClass [SIZE_CL*2] ; for (int i = 0; i< SIZE_CL; i++) { bb[i] = aa[i]; } MyClass::flag = false; cout << bb[3].get(400) << endl; delete[] bb; } А теперь с vector'ом: #include int main() { vector vec; for (int i = 0; i < SIZE_CL; i++) { vec.push_back (new MyClass); vec[i]->set(); }
cout << vec[3]->get(400) << endl;
for (int i = SIZE_CL; i < SIZE_CL*2; i++) { vec.push_back (new MyClass); vec[i]->set(); }
cout << vec[3]->get(400) << endl; } Сравни выводы программы и проанализируй их. Я думаю, с вектором быстрее на порядок, потому что он работает с массивом указателей на объекты и это очень сильно убыстряет работу.

Как правильно писать длинные строковые константы?

Интересует случай многострочных констант при переносе со строки на строку. Собственно сейчас делаю так String query = "SELECT city" + "FROM cities " + "WHERE city='Moscow'";


Ответ

раньше так делал: private static final String SELECT_DUMMY = "" + "SELECT * AS TITLE FROM DUAL" ;
private static final String LIST_ACCOUNTS = "" + "SELECT * FROM ACCOUNTS" ;
private static final String GET_USER_PREFERENCES = "" + "SELECT p.* " + "FROM USER_PREFERENCES up, USERS u" + "WHERE up.user_id = u.id" + "AND u.login_id = ?"; преимущество в том что запрос выглядит практически так же как и в IDE для СУБД (toad/sql developer), большую часть правок можно делать прямо в коде. минус же в том, что неудобно копировать запрос для редактирования в IDE (копируется в месте служебными символами языка для формирования строки), лечится выводом констант в sys out. p.s. раньше так делал сейчас широко используются ORM фреймворки, поэтому хардкод запросов в константах выглядит как минимум странновато

#cccccc \9 - что это?

Доброго всем. встретил недавно в когде CSS вот такую строку:
background-color: #cccccc \9;
Вроде всё понятно, а что такое "\9" не понятно. Что это? И для чего этот параметр?


Ответ

Just google first!

\9 is a "CSS hack" specific to Internet Explorer 7, 8 & 9.
This simply means that the one specific line of CSS ending with a \9 in place of the is only valid in IE 7, 8 & 9.

Обоснованно ли применение полей типа DOUBLE для целых чисел?

Один "товарищ" при создании таблицы в БД использовал поле типа DOUBLE для хранения числа в диапазоне от-100 до 1000 (Макс. 2000), т.е. остатка товара на складе не очень большого магазина, для чисел явно являющихся целыми. Я считаю, что это просто проявление полной безграмотности человека в представлении формата чисел. Или я не прав? Разъясните, так как данный человек в свою очередь заявляет о моей некомпетентности. Уточнение по вопросу: DOUBLE точность до 15 знаков после запятой. Товар точно не весовой. Даже весов никогда небыло в магазине. Это авто-запчасти.


Ответ

Не вижу никакой особенной трагедии в том, что был использован формат DOUBLE для хранения целых чисел. Ну занимает чуток больше пространства - ну и что? Вместо 2 байт - будет 8 байт, подумаешь. Это раньше когда оперативная память 8 кбайт было много, а емкость диска мегабайт рассматривалась как роскошь тогда можно было чего-то оптимизировать. Зато появляется некая универсальность, кто его знает вдруг ваш магазинчик через пару-тройку лет начнет торговать моторным маслом в рОзлив. Хороший прогер должен на уровне архитектуры предусмотреть возможные вывихи в будущем. В общем это не является преступлением, равно как и не является показателем квалификации. Лучше посмотрите на нормальность данных - если они плохо нормализованы - это действительно преступление.

Клик по части прямоугольника

Нужно определить по какой именно части прямоугольника кликнул пользователь ( грубо говоря, по какому именно треугольнику ) Что мы имеем: x, y - координаты клика высота, ширина изображения решение, отдельное спасибо @Yura Ivanov


Ответ

x,y - координаты. w,h - ширина,высота. 1,2,3,4 - номера треугольников начиная с верхнего, дальше по часовой стрелке.
y - x * h / w < 0?"1 или 2":"3 или 4";// относительно главной диагонали y - (h - x * h / w) < 0?"1 или 4":"2 или 3";//относительно побочной диагонали принадлежность линиям соответственно проверка на равенство нулю этих выражений.

Git и GitHub на windows от новичка (часть 2)

Что такое публичный и приватный ssh-ключ? Эта пара ключей для одного пользователя? Если так, то для каждого пользователя я должен в настройки GitHub-а сохранить его публичный ключ? Или достаточно одного публичного ключа для всех? Зачем нужен пароль (passphrase) для соединения по ssh к репозиторию на GitHub? Этот пароль нужен только для доступа к паре ssh ключей, которые хранятся в папке ~/.ssh (имя_пользователя/.shh)? Или этот пароль так же знает репозиторий на GitHub? Пара ключей ssh хранится в папке пользователя на винде. Если я захочу присоединиться к другому репозиторию по ssh, то значит мне надо будет изменить эту пару ssh ключей? Если удалить ветку, то удаляться и все его коммиты? Хотя если подумать, то ветка это всего лишь указатель на коммит, значит удалится этот указатель, а не сами коммиты. Так? Я уже запутался с этими командами перехода_на_коммит/изменения_коммита/удаления_коммитов и т. п. Какие именно команды удаляют коммиты навсегда, а не просто из виду убирают? reset (soft/hard)? revert? еще что-нибудь? Как сделать так, чтобы перестало просить пароль при использовании ssh соединения? Например, когда использую git push или git fetch MS Visual Studio 2010 создал файл main.cpp. При попытки его (и другие файлы с кодом от MS VS) индексировать выводится ошибка:
Fatal: CRLF would be replaced by LF in main.cpp.
Искал в гугле и что-то было про это, но как решить эту проблему я не понял.


Ответ

1) Что такое публичный и приватный ssh-ключ? Сгенерированная пара текстов позволяющих шифровать и расшифровывать данные. Также можно использовать как идентификатор пользователя (правда длинный). Эта пара ключей для одного пользователя? Да. Один пользователь может иметь много ключей. (Один для рабочего компа, один для ноута, ...) Если так, то для каждого пользователя я должен в настройки GitHub'а сохранить его публичный ключ? Или достаточно одного публичного ключа для всех? Насколько мне известно github не позволяет использовать один и тот же ключ в нескольких аккаунтах. Придётся генерировать пару для каждого аккаунта. 2) Зачем нужен пароль(passphrase) для соединения по ssh к репозиторию на GitHub? Чтобы повысить уровень защиты. Оберегает доступ в случае кражи приватного ключа. Этот пароль нужен только для доступа к паре ssh ключей, которые хранятся в папке ~/.ssh(имя_пользователя/.shh)? Или этот пароль так же знает репозиторий на GitHub? Этот пароль никакого отношения к github не имеет, только к ключу. Указывается в момент генерации ключа. 3)Пара ключей ssh хранится в папке пользователя на винде. Если я захочу присоединиться к другому репозиторию по ssh, то значит мне надо будет изменить эту пару ssh ключей? Нет. Ключи используются для доступа к серверу с определённого компьютера. Можно сгенерировать пару, и использовать её для доступа к github, bitbucket, какие-то свои сервера. Ну и добавив ключ в настройках аккаунта вы пользуетесь им для работы со всеми репозиториями которые предоставляет сервис. 4) Если удалить ветку, то удаляться и все его коммиты? Хотя если подумать, то ветка это всего лишь указатель на коммит, значит удалится этот указатель, а не сами коммиты. Так? Не знаю точно. По идее не должны, однако в git используется процедура сжатия, во время которой они могут быть удалены. На SO рекомендуют добавлять тег для ветки (для последнего коммита) и удалять её, тогда коммиты останутся и ветка не будет мозолить глаза. 5)Я уже запутался с этими командами перехода_на_коммит/изменения_коммита/удаления_коммитов и т.п. Какие именно команды удаляют коммиты навсегда, а не просто из виду убирают? reset(soft/hard)? revert? еще что-нибудь? revert не удаляет, лишь обращает изменения новым коммитом. По-вопросу: не знаю, мне всегда хватало reset 6)Как сделать так, чтобы перестало просить пароль при использовании ssh соединения? Например, когда использую git push или git fetch. Сгенерировать новый ключ, во время ввода пароля ничего не вводить. 7)MS Visual Studio 2010 создал файл main.cpp. При попытки его(и другие файлы с кодом от MS VS) индексировать ошибка: Fatal: CRLF would be replaced by LF in main.cpp. Искал в гугле и что-то было про это, но как решить эту проблему я не понял. Windows-specific problem. По-идее ничего страшного, на SO предлагают добавить [core] autocrlf = false сижу на линуксах, поэтому тут помочь не могу. ДОБАВЛЕНО: А что если через один аккаунт, но на разных компьютерах или пользователей в винде? можно сгенерить новый ключ, и добавить его как второй в настройках аккаунта. Т.е. я могу использовать одну пару ключей для любых репозиториев? И вообще все, что угодно(что работает через ssh)? Да. Ну и добавив ключ в настройках аккаунта вы пользуетесь им для работы со всеми репозиториями которые предоставляет сервис. Все репозитории одного аккаунта вы имели ввиду? Да.

Поведение сборщика мусора по отношению к структурам

Недавно прочитал статью Предельная производительность: C# Из-за того, что структуры хранятся в stack’е, они не требуют сборки мусора поясните пожалуйста, это действительно так?


Ответ

Краткое содержание. Нет, структуры не обязательно хранятся в стеке, а объекты -- в куче. Да, с хорошими шансами структура всё же попадёт в стек. Нет, вам не стоит на это рассчитывать, пользоваться этим и пытаться оптимизировать таким образом. На самом деле следует понимать простую вещь: выделение переменной на стеке дешевле, поскольку её можно легко уничтожить, не включая в цикл сборки мусора. Выгода на самом деле только в этом. (Аллокация что на стеке, что в куче -- не более, чем увеличение одного указателя, она очень быстрая.) Очевидно, оптимизатор будет размещать в стеке те переменные, которые, как он может доказать, не нужны после смерти текущего фрейма. Часто про структуры можно такое доказать, но не всегда. Например, структура может быть частью объекта класса, и должна умереть вместе с классом. Или метод будет неявно переписан в стиле продолжений, например, если это генератор (yield return & Co.) или Task<> с async/await. Или переменная попала в замыкание некоторой лямбда-функции. И так далее. Но обычно структуры не нужны после отработки метода, так что оптимизатор может вытеснить их в стек. С другой стороны, про некоторые объекты можно тоже утверждать, что они не нужны после окончания фрейма -- и тогда оптимизатор тоже имеет полное право (но не обязанность, конечно) разместить и их на стеке. Обратите внимание на такую тонкость: если вы возвращаете из метода структуру, вы на самом деле возвращаете её копию, поэтому структура, с которой вы работали, может попасть в стек. С классами же не так: они копируются не по значению, а по ссылке, поэтому возвращаемый объект переживает создавшую его функцию, и следовательно не имеет права жить в стеке. Использованы материалы из блога Эрика Липперта, на которые была ссылка выше. Добавлю ещё пару цитат из Эрика: Использование стека для локальных переменных-структур -- всего лишь оптимизация, которую CLR выполняет для вас. Существенная особенность структур -- семантика копирования по значению, а вовсе не то, что в некоторых случаях их уничтожение может быть оптимизировано рантайм-библиотекой. В подавляющем большинстве программ, выделение и уничтожение локальных переменных не будут критически важным фактором производительности. Превращение типа, который должен на самом деле быть ссылочным типом, в структуру -- это нано-оптимизация, дающая выгоду в пару наносекунд, и вероятно не стоящая того. На вашем месте я бы проводил такую оптимизацию только если данные профилирования покажут, что существует реальная, большая проблема у ваших реальных клиентов, которую можно исправить использованием структур. Не имея таких данных на руках, я всегда бы делал выбор между классами и структурами основываясь на том, представляет ли тип семантически значение или ссылку на что-то. (То есть, имеет ли объект смысл помимо значения, содержащегося в нём, обладает ли он самостоятельной сущностью -- VladD)

Как поступит Java при компиляции?

Код: int x = 1; if (x != 2) { int y = 2;} int z = x + y; System.out.print(z); Собственно говоря, этот код, несмотря на if, в любом случае эквивалентен этому: System.out.print(3); А теперь сам вопрос Что запишет в скомпилированный файл java? Короткую или длинную версию кода?


Ответ

Маленький эксперимет. Вариант 1 public static void main(String[] args) { int x = 1; int y = 0; if (x != 2) { y = 2;} int z = x + y; System.out.print(z); } Никаких изменений. 1 в 1. Вариант 2 Исходник: public static void main(String[] args) { int x = 1 + 4; int y = 0 + x; if (x != 2) y = 2; int z = x + y - y + y - x + x; System.out.print(z); } декомпиляция: public static void main(String[] args) { int x = 5; int y = 0 + x; if (x != 2) y = 2; int z = x + y - y + y - x + x; System.out.print(z); } Как и ожидалось, ушло только очевидное сложение. Вариант 3 А вот с константами всё интереснее: Исходник: public static void main(String[] args) { final int x = 1 + 4; final int y = 1 + x; final int z = x + y - y + y - x + x; System.out.print(z); } Декомпиляция: public static void main(String[] args) { int x = 5; int y = 6; int z = 11; System.out.print(11); } Вот тут уже оптимизатор оттянулся как захотел) Инструменты JDK 1.7.0.9 + JD 0.6.2

Сертификация Microsoft. Есть ли смысл?

В поисках первой работы на junior .NET разработчика появилась идея получить сертификацию. Подскажите, есть ли в этом практический смысл? Увеличит ли это шансы? Как я указал - работа первая, т.е. опыта коммерческой разработки нет. Конкретно, я думал получить MCSD: Web Applications. Для этого необходимо сдать 3 экзамена: Programming in HTML5 with JavaScript and CSS3 (бесплатно) Developing ASP.NET 4.5 MVC Web Applications (80$) Developing Windows Azure and Web Services (80$) В принципе подготовиться - не проблема, но не уверен есть ли в них смысл и стоит ли тратить 160$.


Ответ

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

Удобный PL SQL редактор [закрыт]

Расскажите пожалуйста, кто какими инструментами пользуется для работы с PL/SQL кодом? Уже давно использую для подобных задач SQL Developer компании Oracle, но в нем многие вещи не устраивают: отсутствие нормальной подсветки кода, постоянно "отваливающиеся" connections, ну и еще много мелочей.
Может есть лучшие средства (программы), облегчающие жизнь разработчику?
P.S. Желательно free products, поскольку рабочая станция корпоративная


Ответ

Видимо Oracle SQL Developer лично у вас как-то нестабильно работает. Он очень простой и удобный, не то что всякие PL/SQL Developer и TOAD, где куча ненужного барахла. Продолжайте использовать Oracle SQL Developer!

Getter для public static final (java). Есть ли смысл?

Имеет ли смысл скрывать public static final константы и делать геттер либо нет? Вышел небольшой спор... Спасибо! :)


Ответ

Универсальное правило ровно одно: следуйте семантике, смыслу кода.
Если вы экспортируете константу, смело выставляйте наружу public static final. Например:
class GlobalConstants { public static final int DAYS_IN_WEEK = 7; }
Если же вы экспортируете что-то, за чем есть или может быть логика, что может поменяться, сделайте это лучше свойством, чтобы потом можно было безболезненно для клиентов вашего кода эту логику поменять.
class MyCar { private static final String manufacturerName = "ЗАЗ"; public String getManufacturer() { return manufacturerName; } }
Если завтра вы пересядете на "Феррари", у клиентов, которые скомпилировались со старой версией вашей библиотеки, не будет проблем. (А вот если бы ваша строка была константой, она оказалась бы жёстко вкомпилированной в код клиентов, и они бы продолжали считать, что вы ездите на "Запорожце".)

Подобный вопрос для C# уже обсуждался на сайте

Закрытое наследование: request for member 'eat' in 'b', which is of non-class type

Здравствуйте. У меня есть следующий код а-ля HelloWrold: #include using namespace std;
class A { public : void eat ()const { cout << "inside eat" << endl; }; };
class B : private A { public : using A::eat; };
int main() {
B b(); // {1} B b; // {2} b.eat(); return 0; } Собственно вопрос: если закомментировать строку {1} и раскомментировать строку {2} то все компилируется. А если наоборот закомментировать строку {2} и раскомментировать строку {1} то выдается сообщение об ошибке "request for member 'eat' in 'b', which is of non-class type 'B ()()" В чем же причина такого поведения компилятора? Заранее спасибо


Ответ

Потому, что B b(); это не определение переменной, а определение функции b без аргументов, которая возвращает B. Проверить это легко - добавьте в класс B конструктор по умолчанию, который выводит в лог/консоль. #include
using namespace std;
class B { public : B() { cout << "bbb" << endl; } };
int main() { B b(); return 0; } В логе будет пустота. Детали можно почитать в стандарте в пунктах 6.8 и 8.2

Выбор случайного элемента массива, вероятность выпадания которого предопределена

Есть такой набор данных:
$items = array( array( 'name' => 'Элемент #1', 'chance' => 1, ),
array( 'name' => 'Элемент #2', 'chance' => 5, ),
array( 'name' => 'Элемент #3', 'chance' => 10, ), );
Для каждого элемента массива предопределена вероятность — в ключе 'chance'
Задача: выбрать случайный элемент из этого набора, учитывая, что вероятность того что выпадет «Элемент #2» в 5 раз выше, чем «Элемент #1», а «Элемент #3» — в 10 раз выше, чем у «Элемент #1».
Если точнее, то, наверно, так:
Элемент #1 — вероятность: 1/16 Элемент #2 — вероятность: 5/16 Элемент #3 — вероятность: 10/16
Набросал такой алгоритм
$items = [...]; // входной массив (см. выше)
$items_set = array();
foreach ($items as $item_id => $item) { for ($i = 0; $i < $item['chance']; $i++) $items_set[] = $item_id; }
// теперь $items_set представляет собой такой массив: // [0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] // то бишь, индекс элемента входного массива повторяется столько, // сколько у него «шансов» быть избранным
$rand_id = $items_set[array_rand($items_set)]; $rand_item = $items[$rand_id];
На выходе $rand_item хранит как-раз то, что необходимо — один из элементов входного массива. И все бы хорошо, если бы при добавлении элемента с вероятностью 200, массив $items_set не рос на 200 элементов. И таких может быть несколько.
Вопрос: есть ли какой-то более адекватный способ решения задачи? Если алгоритм будет уметь оперировать с элементами с вероятностью = 0.5 — будет вообще здорово (мой вариант к этому не приспособлен, приходится предварительно подбирать множитель для всех «шансов» так, чтобы минимальный был = 1).


Ответ

да, такой алгоритм есть. Он заключается в том, что нужно сформировать массив вида [1,6,16]. ( То есть, если есть массив вероятностей [1,5,10], то нужный массив это такой, что элемент в позиции n - это сумма элементов первого массива от 1 до n). Последний элемент этого массива - это суммарное кол-во вариантов. Как использвоать: генерируем случайное число и проходим по массиву, пока не найдем элемент, который больше сгенерированного числа (я предполагаю, что случайные числа генерятся в диапазоне от 0 до сумма минус 1). Но если элементов больше 7-10, то лучше уже подумать о бинарном поиске, благое дело, он будет быстрым (массив то гарантированно отсортирован).

Почему следующая программа выводит 1?

main(_) { printf("%d",_); }
gcc -o test.c test test.exe 1


Ответ

Из стандарта (§ 5.1.2.2.1) следует, что так писать функцию main нельзя, и результат зависит от конкретной имплементации: The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /* ... */ } or equivalent; or in some other implementation-defined manner. Предположу, что в вашем случае: Бестиповый аргумент посчитался int'ом, как в старых версиях C. То же относится к возвращаемому значению функции. argc отобразился на эту переменную (если вы запускаете программу без аргументов, argc == 1). Можно проверить эту версию, передав в программу аргументы командной строки и проверив, как поменяется вывод программы. Чтобы компилятор переключился на более современный диалект языка, попробуйте ключ -std=c99

Шифрование ссылок для скачивания

Вопрос довольно популярный, объясните пожалуйста каким образом можно наиболее адекватно шифровать ссылки для скачивания. То есть пользователь вошел -> для него генерируется ссылка, допустим на zip архив, ну и удаляется после скачки. Ни когда таким не занимался, стало интересно.


Ответ

Можно пользоваться средствами веб сервера: модуль SecureLink для nginx (вовсю использую); и, кажется, mod-auth-token для Apache. Upd. Можно написать и свою реализацию на том же php, но есть очевидный минус: перформанс. Чтобы не показывать истинный адрес файла, придётся пропускать его контент сквозь работающий php скрипт в течение всего времени скачивания. Т.е. в памяти будет висеть по тяжеленному процессу php на каждую сессию скачивания. А веб сервер делает то же самое, легко и изящно. А, ещё можно создавать временную копию ценного файла, или, лучше, линк на него, со странным именем-абракадаброй, и стирать через опр. время.

Можно ли это назвать хеш-таблицей. Если нет то почему ?

Почитал кормена и написал хеш-таблицу на основе сцепления элементов. Можно ли это назвать хеш-таблицей и если нет то почему, какие ошибки есть логические ? node.hpp #ifndef NODE_HPP #define NODE_HPP
template class list;
template class node { private: friend class list;
private: node* m_next; node* m_prev; T m_data;
public: node() : m_next(0) , m_prev(0) , m_data(0) {}
explicit node(T d) : m_next(0) , m_prev(0) , m_data(d) {} T get_data() { return m_data; } };
#endif // NODE_HPP list.hpp #ifndef LIST_HPP #define LIST_HPP
#include #include
#include "node.hpp"
template class list { private: node* m_head; node* m_tail; unsigned m_size;
public: list() : m_size(0) , m_head(0) , m_tail(0){}
node* get_new_node(T d) const; node* find(T data) const; void insert_at_front(T data); void insert_at_back(T data); void delete_at_front(); void delete_at_back(); bool is_empty() const; void print() const; node* get_begin() const { return m_head; } node* get_end() const { return m_tail; } unsigned get_size() const { return m_size; } };
template node* list::get_new_node(T data) const { node* n = new node(data); assert(n != 0); return n; }
template bool list::is_empty() const { if(m_head == 0) { return true; } return false; }
template void list::print() const { if(is_empty()) { return; } node* t = m_head; while(t != 0) { std::cout << t->m_data << " "; t = t->m_next; } }
template node* list::find(T data) const { if(is_empty()) { return 0; } node* t = m_head; while(t != 0 && t->m_data != data) { t = t->m_next; } return t; }
template void list::insert_at_front(T data) { node* n = get_new_node(data); if(m_head == 0) { m_head = m_tail = n; n->m_next = n->m_prev = 0; ++m_size; } else { n->m_next = m_head; if(m_head != 0) { m_head->m_prev = n; } m_head = n; n->m_prev = 0; ++m_size; } }
template void list::insert_at_back(T data) { node* n = get_new_node(data); if(m_tail == 0) { m_head = m_tail = n; n->m_next = n->m_prev = 0; ++m_size; } else { m_tail->m_next = n; n->m_prev = m_tail; m_tail = n; ++m_size; }
}
template void list::delete_at_front() { if(is_empty()) { return; } else { node* t = m_head->m_next; t->m_prev = 0; delete m_head; m_head = t; --m_size; } }
template void list::delete_at_back() { if(is_empty()) { return; } else { node* t = m_tail->m_prev; t->m_next = 0; delete m_tail; m_tail = t; --m_size; } }
#endif // LIST_HPP hash_table.hpp #ifndef HASH_TABLE_HPP #define HASH_TABLE_HPP
#include "list.hpp"
template class hash_table { private: list** m_table; unsigned m_size;
private: int get_hash(int key);
public: explicit hash_table(unsigned); T find(const T&, const T&); void insert(const T&, unsigned); void remove(const T&); };
template hash_table::hash_table(unsigned size) { m_size = size; m_table = new list*[m_size]; for(int i = 0; i < m_size; ++i) { m_table[i] = new list(); } }
template int hash_table::get_hash(int key) { return (key % m_size); }
template T hash_table::find(const T& d, const T& i) { int h = get_hash(i); node* n = m_table[h]->find(d); assert(n != 0); return n->get_data(); }
template void hash_table::insert(const T& d, unsigned key) { unsigned h = get_hash(key); m_table[h]->insert_at_front(d); }
#endif // HASH_TABLE_HPP Поправил код find(...) template T hash_table::find(const T& i) { int h = get_hash(i); if(m_table[h]->get_begin() != 0) { return m_table[h]->get_begin()->get_data(); } return 0; } но так получается что функция всегда возвращает только голову списка а если есть коллизия то этот случай не учитывается ... ?


Ответ

Есть несколько замечаний по реализации: Непонятна сигнатура find(T, T). Почему не find(Key)? Непонятно ваше разделение для элементов хэш-таблицы. То есть, сигнатуры методов должны выглядеть как insert(Key, Value) / find(Key) / remove(Key), либо как insert(Value) / find(Value) / remove(Value) для случая, когда в хэш-таблице хранятся не пары ключ-значение, а сами значения. Других вариантов нет. Не предложена имплементация remove(T). Вместо траты времени на реализацию своего std::list, лучше бы уж написали метод удаления элементов из хэш-таблицы. Крайне странное решение, в котором вызов функции find() coredump'ится в случае отсутствующего в хэш-таблице значения. Вообще, предложенный код, за исключением последних пятнадцати строчек, не имеет к хэш-таблицам никакого отношения, а просто предлагает какой-то неочевидный способ реализации аналога std::list. Решение с наследованием node ← list, кстати, кажется очень странным. А так, ну да, обычная хэш-таблица с chaining'ом для резолвинга коллизий.

Вычисления корня из произведения

Доброго времени суток! Дано нескольких чисел порядка 10^12, не являющихся квадратами, произведение которых гарантированно является квадратом некоторого числа. Проблема в том, что, произведение это, очевидно, > 10^20 то есть значительно превышает размер unsigned long long Собственно, вопрос: как из этого произведения вычислить точный корень за как можно меньшее время? Появляется естественное желание раскладывать числа на простые множители, после чего перемножать заново, но их брать степени в два раза меньше. Но разложение таких чисел каждого займет много времени и памяти. Заранее спасибо всем откликнувшимся!


Ответ

Давайте попробуем вот как:
Пусть наши числа a, b, и их разложение на простые множители выглядит так:

Можно посчитать t = НОД(a, b), не раскладывая числа на множители при помощи алгоритма Евклида, тогда

где

Рассмотрим числа

Эти числа обязаны являться квадратами, т. к. каждый простой показатель степени входит либо в a₀, либо в b₀ (ясно, почему?). Из них можно извлечь корень.
Далее,

Всё.

В качестве альтернативного решения: вычислим приблизительный корень типа double из каждого сомножителя. Точность вычисления корня (sqrt(double)) 52 значащих бита, то есть 15 десятичных разрядов. Для чисел точностью в 12 разрядов корень будет около 6 разрядов, то есть точность корня будет 15 - 9 = 6 знаков после запятой. То же для второго сомножителя. Перемножим полученные корни. Точность произведения будет 5 знаков после запятой. Округлив произведение до целого, получим точный результат (для этого достаточен был бы 1 знак после запятой, а у нас их аж 5).

PS: почему бы не включить математическую нотацию здесь, как и на маткоде?