Страницы

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

среда, 12 декабря 2018 г.

Влияние кол-ва запросов в транзакции на производительность

Нужно ли отправлять изменения в БД одной транзакцией, или каждый INSERT, UPDATE, DELETE лучше выполнять отдельной транзакцией? Что лучше при выполнении 10 несвязанных запросов (не нужно откатывать предыдущий запрос при ошибке последующего), отправить их одной транзакцией, или каждый по отдельности? Какой вариант лучше для производительности приложения и субд?


Ответ

В общем случае ни первый ни второй вариант не являются оптимальными с точки зрения производительности.
Если нужно удалить(вставить/поменять) действительно большое количество строк, в первом случае мы получаем большие расходы на открытие, закрытие большого количества транзакций.
Во втором случае имеем слишком огромную транзакцию, которая тоже под конец работы будет долго закрываться, да ещё и рискуем упасть, т.к. размеры транзакции ограничены(видел такую ошибку всего на нескольких миллионах строк).
Как-то писал скрипт удаления "ненужных" данных. Сталкивался с обеими проблемами. Скрипт запускался на выходных, и удалял несколько десятков миллионов строк. Т.е. проблемы блокировок и прочего не волновали, в приоритете была скорость. Чтобы наглядно продемонстрировать, написал небольшой скрипт. MS SQL Server
Кратко что он делает:
T_TABLE - таблица с данными T_RESULT - таблица с результатами эксперимента P_INSERT_ROWS @Count - вставляет в таблицу T_TABLE @Count строк P_DALATE_ROWS @Count, @Pack - удаляет из таблицы T_TABLE все строки в транзакциях по @Pack штук, и записывает затраченное время в таблицу T_RESULT
Финальный скрипт запускает в цикле вставку 1 000 000 строк, и их удаления пачками по 1, 10 .. 1 000 000 штук. И затем выводит содержимое T_RESULT
Скрипт:
USE tempdb; GO IF OBJECT_ID('P_INSERT_ROWS', 'P') IS NOT NULL DROP PROC P_INSERT_ROWS; IF OBJECT_ID('P_DELETE_ROWS', 'P') IS NOT NULL DROP PROC P_DELETE_ROWS; IF OBJECT_ID('T_TABLE', 'U') IS NOT NULL DROP TABLE T_TABLE; IF OBJECT_ID('T_RESULT', 'U') IS NOT NULL DROP TABLE T_RESULT; GO CREATE TABLE T_TABLE ( id INT IDENTITY(1,1), Number INT, String NVARCHAR(4000) ) CREATE INDEX IN_T_TABLE_NUMBER ON T_TABLE(Number ASC) CREATE TABLE T_RESULT ( execute_time DATETIME, Cnt INT, Pack INT ) GO CREATE PROC P_INSERT_ROWS @Count INT AS ;WITH CTE AS( SELECT 1 N UNION ALL SELECT N+1 FROM CTE WHERE N<@Count ) INSERT T_TABLE SELECT N, LEFT(REPLICATE(N, 100),4000) FROM CTE OPTION(MAXRECURSION 0) GO CREATE PROC P_DELETE_ROWS @Count INT, @Pack INT AS DECLARE @TTT DATETIME = GETDATE(); DECLARE @NumberStart INT = 1 WHILE @NumberStart < @Count BEGIN BEGIN TRAN; DELETE FROM T_TABLE WHERE Number BETWEEN @NumberStart AND @NumberStart + @Pack - 1 OPTION(RECOMPILE); COMMIT TRAN; SET @NumberStart += @Pack; END; INSERT T_RESULT SELECT GETDATE()-@TTT execute_time, @Count Cnt, @Pack Pack GO SET NOCOUNT ON; DECLARE @Count INT = 1000000, @Pack INT = 1 WHILE @Pack <= @Count BEGIN EXEC P_INSERT_ROWS @Count EXEC P_DELETE_ROWS @Count, @Pack SET @Pack *= 10; END SELECT * FROM T_RESULT GO
Содержимое T_RESULT
execute_time Cnt Pack 1900-01-01 00:15:05.183 1000000 1 1900-01-01 00:01:56.003 1000000 10 1900-01-01 00:00:32.200 1000000 100 1900-01-01 00:00:22.370 1000000 1000 1900-01-01 00:00:21.940 1000000 10000 1900-01-01 00:00:22.663 1000000 100000 1900-01-01 00:01:10.327 1000000 1000000
Как видим, лучший результат по времени выполнения имеем, когда удаляется в одной транзакции пачками по 10000 штук, т.е. это намного эффективнее, чем удалять по одной записи в транзакции, и эффективнее, чем удалить все строки в одной транзакции. Эксперимент не строгий, запуски влияют друг на друга, но всё равно показательно.
UPD: Добавлю, что на практике, транзакции в реальной жизни не часто бывают большими. Кроме запросов вида DELETE FROM T, пожалуй.:) В этом случае да, чаще всего если есть возможность обернуть несколько действий в одну транзакцию - лучше обернуть.

Регулярное выражение для поиска мобильного телефона в тексте

Подскажите регулярное выражение для поиска номера мобильного телефона в тексте.
Номера телефонов вводятся разными пользователями и в совершенно непредсказуемом формате, например могут участвовать -+()_ пробелы и еще не известно на что хватит фантазии.
Примеры телефонов:
8 900 000-00-00
+7 (900) 000 00-00
+7 9001112233
89001112233
8(900) 111-2233
и т.д


Ответ

Думаю, примерно так:
/(\+7|8)[- _]*\(?[- _]*(\d{3}[- _]*\)?([- _]*\d){7}|\d\d[- _]*\d\d[- _]*\)?([- _]*\d){6})/g
console.log( "8 900 000-00-00\ +7 (900) 000 00-00\ +7 9001112233\ 89001112233\ 8(900) 111-2233\ 8 (1234) 12 12 12\ 8 (12-34) 12 12 12\ 8 ( 123 ) 412 12 12".match( /(\+7|8)[- _]*\(?[- _]*(\d{3}[- _]*\)?([- _]*\d){7}|\d\d[- _]*\d\d[- _]*\)?([- _]*\d){6})/g )) .as-console-wrapper.as-console-wrapper { max-height: 100vh }

Кодирование текста в произвольный двоичный код и обратно. Пример: “А” <-> “01100011”

Мне нужно преобразовать строку, например "А", в строку двоичного кода, например "01100011", потом обработать немного двоичный код, пропустив его по функции "Исключающее ИЛИ" с другим двоичным кодом, например "01100011" с "11000010", тогда выйдет "10100001", и обратно перевести получившийся код в читаемую строку, например в "Т".
При этом, я хочу использовать русскую, английскую и украинскую раскладку и цифры, со знаками припинания. Не подскажете, как это сделать на Python 3?
Вопрос состоит в том как в Python преобразовать строку в двоичный код и обратно используя любой алгоритм кодировки?


Ответ

Чтобы произвольный текст превратить в "01"-строки (биты):
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'): bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:] return bits.zfill(8 * ((len(bits) + 7) // 8))
И обратно:
def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'): n = int(bits, 2) return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'
Пример:
>>> text_to_bits("мiр"))) '1101000010111100011010011101000110000000' >>> text_from_bits(_) мiр
См. Convert binary to ASCII and vice versa

Чтобы выполнить XOR над двумя строками, нет необходимости биты в виде ascii-строк выражать:
from itertools import cycle
def xor(message, key): return bytes(a^b for a, b in zip(message, cycle(key)))
Достаточно текст в байты закодировать, используя .encode() метод:
>>> key = b'key' >>> xor('hello world'.encode(), key) b'\x03\x00\x15\x07
Y\x1c
\x0b\x07\x01' >>> xor(_, key).decode() # и обратно 'hello world'
См. Перевести с PHP на python: XOR с ключём для строки
Для больших строк, можно numpy использовать:
import numpy as np # pip install numpy
def slow_xor(aa, bb): a = np.frombuffer(aa, dtype=np.byte) b = np.frombuffer(bb, dtype=np.byte) return np.bitwise_xor(a, b).tostring()
Пример:
>>> slow_xor(b'hello...', 'миръ'.encode()) b'\xb8\xd9\xbc\xd4\xbe\xae\xff\xa4'
Если вы хотите ускорить эту функцию, см. Simple Python Challenge: Fastest Bitwise XOR on Data Buffers

Правильное переопределение Dispose(bool disposing)?

Имеется класс, реализующий паттерн Disposable
internal class SomeDisposableClass : IDisposable { private readonly System.IO.Stream _managedResource;
private bool _disposed;
public SomeDisposableClass(System.IO.Stream managedResource) { _managedResource = managedResource; }
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
protected virtual void Dispose(bool disposing) { if(_disposed) { return; }
if(disposing) { _managedResource?.Dispose(); }
_disposed = true; } }
А есть класс, наследующийся от него:
internal sealed class DerivedDisposableClass : SomeDisposableClass { private readonly System.IO.Stream _anotherResource;
public DerivedDisposableClass(System.IO.Stream managedResource, System.IO.Stream anotherResource) : base(managedResource) { _anotherResource = anotherResource; }
protected override void Dispose(bool disposing) { _anotherResource?.Dispose();
base.Dispose(disposing); } }
Вопрос: Нужно ли в классе-наследнике вводить флаг _disposed? Если да, то какой от этого профит?
И ещё: Может кто-нибудь на пальцах объяснить, какова польза от GC.SuppressFinalize(this) в классе-родителе (при условии, что наследник будет иметь финализатор)?


Ответ

Флаг _disposed в вашем варианте наследнику нужен потому что как ему иначе определить что его уже нет?
Чтобы не заводить отдельный флаг на каждого наследника - можно немного изменить родителя.
Вариант 1. Вынесите проверку флага наружу, в невиртуальный Dispose(). В таком случае наследник будет просто знать что переопределенный Dispose(bool) будет вызван только один раз и проверка будет не нужна.
Вариант 2. Сделайте защищенное (protected) свойство IsDisposed в базовом классе.
От GC.SuppressFinalize(this) большая польза - он отменяет финализатор, что позволяет сборщику мусора собрать ваш объект за одну попытку а не за две.

Тем не менее, полный паттерн Disposable давно уже устарел. Гораздо красивее выглядит альтернативный подход, при котором считается недопустимым владение одновременно и управляемым и неуправляемым ресурсом в одном классе.
Недостатки классического паттерна Disposable:
он создает избыточную нагрузку на память потому что "тяжелые" объекты с финализаторами не могут быть собраны GC пока финализатор не отработает или не будет отменен; он вызывает утечку ресурсов при выгрузке домена приложений (а это частое явление в том же ASP.NET).
Согласно более современному подходу, обычные классы в принципе не могут владеть неуправляемыми ресурсами - а потому им не нужен ни финализатор, ни метод Dispose(bool)
Для неуправляемых же ресурсов полагается делать управляемые обертки, желательно - на основе SafeHandle, но можно и на основе CriticalFinalizerObject
Более подробно этот подход расписал VladD в вопросе Как и когда нужно имплементировать IDisposable?

C#: наблюдение за переменной другого класса

Классический пример: класс Lamp , описывающий электрическую лампочку, с состояниями On (bool on = true) и Off (bool on = false). Я хочу отслеживать значения этой переменной из другого класса (например, LightingControl), чтобы этот класс реагировал на изменения состояния лампочки. Из класса Lamp не могут быть вызываны никакие методы других классов, так как класс Lamp является моделью непрограммируемого электрического прибора. Как это реализовать?
Заготовка кода для ответа:
class Lamp(){
public bool on;
public Lamp(bool onOrOffSignal){ this.on = onOrOffSignal; }
// ... }
class LightingControl(){
Lamp lamp = new Lamp();
// ...
// это реагирование должно происходить в режиме реального времни if (Lamp.on == true){ emergencyLighting.turnOff(); } else { emergencyLighting.turnOn(); }
}


Ответ

INotifyPropertyChanged, он должен быть известен вам по экспериментам с WPF:
class Program { static void Main(string[] args) { Lamp lamp = new Lamp(); LightingControl lc = new LightingControl(lamp); lamp.IsOn = true; lamp.IsOn = false; Console.ReadKey(); } }
class Lamp : INotifyPropertyChanged { bool isOn; public bool IsOn { get => isOn; set { isOn = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsOn))); } }
public event PropertyChangedEventHandler PropertyChanged; }
class LightingControl { Lamp _lamp;
public LightingControl(Lamp lamp) { _lamp = lamp; lamp.PropertyChanged += OnLampPropertyChanged; }
private void OnLampPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(Lamp.IsOn)) { Console.WriteLine($"Lamp {(_lamp.IsOn ? "On" : "Off")}!"); } } }
Связанный вопрос: Как организовать взаимодействие объекта с его наблюдателем

Падает производительность при использования предиката для гибкой сортировки в LINQ запросе

Пытаюсь сделать LINQ запрос в котором можно менять поле (одно) по которому нужно производить сортировку. Использование переменной предиката позволяет это
public void GetMyData(string sortFieldName) { Func orderPredicate = null; switch (sortFieldName) { case "FIELD_STRING": orderPredicate = x => x.FIELD_STRING; case "FIELD_INT": orderPredicate = x => x.FIELD_INT; case "FIELD_DATE": orderPredicate = x => x.FIELD_DATE; default: orderPredicate = x => x.FIELD_DATE; }
var queryResult = db.MyEntity.OrderBy(orderPredicate);
//...some logic
}
Но резко (в десятки раз) падает производительность по сравнению с прямым заданием условия сортировки. Насколько понимаю, должно помочь Expression. Меняю тип переменной
Expression> orderPredicate = null;
Но в рантайме выдаёт исключение
Не удалось привести тип "System.DateTime" к типу "System.Object". LINQ to Entities поддерживает только приведение типов-примитивов моделей EDM или типов перечисления.
Как же быть? Ведь, если я буду использовать прямое задание условия
public void GetMyData(string sortFieldName) { var query = db.MyEntity; var orderedQuery = query.OrderBy(x => x.FIELD_DATE); switch (sortFieldName) { case "FIELD_STRING": orderedQuery = query.OrderBy(x => x.FIELD_STRING); break; case "FIELD_INT": orderedQuery = query.OrderBy(x => x.FIELD_INT); break; case "FIELD_DATE": orderedQuery = query.OrderBy(x => x.FIELD_DATE); break; }
//...some logic
}
, мне будет трудно усложнить запрос дополнительными инструкциями Where, Include и т.д.


Ответ

Проблема в том, что когда вы пишите вот так:
Expression> orderPredicate; orderPredicate = x => x.FIELD_DATE;
Компилятор делает вот так:
var _param = Expression.Parameter(typeof(MyEntity), "x"); orderPredicate = Expression.Lambda>( Expression.Convert( Expression.Property(_param, "FIELD_DATE"), typeof(object) ), _param );
Вот на этот самый Expression.Convert EF и ругается. Для того чтобы не было преобразования - возвращаемый тип делегата обязан совпадать с типом свойства, что в свою очередь означает что общую переменную orderPredicate вы использовать не можете.

Теперь как строить такие запросы. А строятся они очень просто - через накопление IQueryable
IQueryable q = db.MyEntity; switch (sortFieldName) { case "FIELD_STRING": q = q.OrderBy(x => x.FIELD_STRING); case "FIELD_INT": q = q.OrderBy(x => x.FIELD_INT); case "FIELD_DATE": q = q.OrderBy(x => x.FIELD_DATE); default: q = q.OrderBy(x => x.FIELD_DATE); }
Никакого усложнения тут нет, полученный запрос можно точно также дополнять другими условиями:
q = q.Where(x => x.Foo > 42);

PS поскольку у вас в параметре sortFieldName передается имя свойства, построение выражения можно еще немного упростить. Да, класс Queryable не дает нам вызвать OrderBy с неизвестным заранее именем свойства - но никто не мешает "раскрыть" этот метод и работать непосредственно с IQueryable
IQueryable q = db.MyEntity;
var entityParam = Expression.Parameter(typeof(MyEntity)); var propExpr = Expression.Property(entityParam, sortFieldName) q = q.Provider.CreateQuery( Expression.Call(typeof(Queryable), "OrderBy", new [] { entityParam.Type, propExpr.Type }, // Типы-параметры для метода Queryable.OrderBy<,> q.Expression, Expression.Quote(Expression.Lambda(propExpr, entityParam)) ) );
Также вместо того чтобы делать это вручную - можно использовать библиотеку System.Linq.Dynamic, скачав ее из nuget:
q = q.OrderBy(sortFieldName);

Почему operator++ должен возвращать const T?

const T T::operator++(int) { T tmp = *this; ++(*this); return tmp; }
Рассмотрим такой вариант реализации постфиксного оператора инкрементирования. Почему требуется возвращать именно const T, а не T? Такой вариант реализуется для типа int, а нужно ли мне реализовывать этот оператор для своего пользовательского типа аналогично?
Я придерживался негласного правила, что при разработке классов (типов) в случае если непонятно (или еще не сформулировано) требуемое поведение то следует организовать поведение, какое предоставляет int. int возвращает const int. А нужно ли и мне так?


Ответ

Нет необходимости делать возвращаемый тип константым, чтобы избежать двойного инкремента ++++. Достаточно объявить оператор инкремента только для lvalue объектов (добавить & в сигнатуру):
struct T { T operator++(int) & { return *this; } };
int main() { T t;
t++; // ok t++++; // ошибка }

Помощь с sql запросом

Есть таблица table1
id city 1 Москва 2 Воронеж 3 Самара
Есть таблица table2
id id_city rating 1 1 22 2 1 66 3 1 95 4 2 12 5 2 37 6 2 13 7 3 68 8 3 54 9 3 27
Связь по полям table1.id = table2.id_city Примерный алгоритм: Берем 1-ый город и выбираем у него самый большой рейтинг. Затем берем 2-ой город и выбираем у него самый большой рейтинг. Тоже самое с 3-им. Затем все повторяется, начинаем с 1-ого города. Необходимо сделать такой запрос, чтобы результат был следующим:
id_city rating 1 95 2 37 3 68 1 66 2 13 3 54 1 22 2 12 3 27


Ответ

set @pk1 =''; set @rn1 =1;
SELECT id_city, rating
FROM (SELECT id_city, rating, @rn1 := if(@pk1=id_city, @rn1+1,1) as rowNumber, @pk1 := id_city FROM (SELECT id_city, rating FROM table2 ORDER BY id_city, rating desc ) A ) B order by rownumber, id_city
Решение можно проверить тут http://sqlfiddle.com/#!9/3683a4/5

Можно ли в структуру вставить ф-цию?

Например:
struct st { int n = 0; int m = 0; int summa (int i, int j) { return n + m; } }
код, конечно не работает, но можно ли сделать что-то подобное в Си?


Ответ

В таком виде — нет, это вам не C++. Но ничто не мешает передавать this явно.
К слову, пространств имён тут тоже нет, так что функцию придётся вытащить за пределы структуры.
И вообще, Си — это язык низкого уровня, без прикрас и синтаксического сахара. Так что извольте раскладывать всю программу по полочкам.
struct st { int n; int m; };
void st_constructor(struct st* this) { this->n = 0; this->m = 0; }
int st_summa(const struct st* this) { return this->n + this->m; }

Что такое компаратор?

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


Ответ

Ну, например, как выполняется сортировка?
sort(v.bein(),v.end());
При этом сортируемые элементы сравниваются просто с помощью оператора <. Вот он и есть компаратор по умолчанию. Но если вы хотите какую-то очень хитрую сортировку, то это делается так
sort(v.bein(),v.end(), comp);
где comp и есть компаратор - т.е. функция, функциональный объект, лямбда-выражение - словом, которому можно передать два элемента для сравнения.
Например, по умолчанию сортировка строк будет сравнивать их содержимое. А сортировка
sort(v.bein(),v.end(), // Вот это лямбда-выражение и есть компаратор: [](const string& a, const string& b){ return a.length() < b.length(); } );
будет сортировать строки по длине.
То же самое можно записать и с обычной функцией:
// Здесь компаратор - функция comp: bool comp(const string& a, const string& b) { return a.length() < b.length(); }
sort(v.bein(),v.end(), comp);

PHP двойная или одинарная кавычка и конкатенация - что быстрее

Для того, чтобы собрать строку можно использовать два варианта. Первый с помощью двойных кавычек (данные парсятся) например:
$text = "Здесь любой текст и переменная $test";
Или второй вариант с помощью конкатенации:
$text = 'Здесь любой текст и переменная '.$test;
Какой вариант будет работать быстрее? И зависит ли разница в скорости от количества переменных в строке? Просто услышал мнение, что конкатенация занимает больше времени. Хочется услышать мнение экспертов.


Ответ

раз уже вчера с @АлексейШиманский затронули тесты, а @StackOverflow поделился ссылкой на древнюю как динозавры статью с какими то тестами от 2008 года, то решил проверить один из этих тестов в 2017м. Железо почти из той же эпохи i7-980x и 10 ГБайт памяти в наличии win10х64, Open Server, проверяем на пхп 5.6 и 7.0.22.
запуск тестовых функций несколько переписан.
for($i = 1; $i <= 4;$i++){
$f = "quotes_$i"; $ts = microtime(true);
call_user_func($f, $_1, $_2, $_3, $_4, $_5, $_iterator);
$time = microtime(true) - $ts; print "$f - $time
"; }
тестируются 4 функции, в каждой по 5 млн итераций, в строку подставляется 5 переменных:
подстановка в строки вида "qwe $var asd" подстановка в строки вида "qwe {$var} asd" конкатенация с одинарными кавычками 'qwe'.$var.'asd' использование sprintf
для пхп 5.6х32 результаты следующие (5 запусков, средний):
1. 4,143 сек 2. 3,827 сек 3. 6,866 сек 4. 12,378 сек
при запуске в консоли результат в аналогичный.
для пхп 5.6х64 время несколько увеличивается (здесь и далее по 3 запуска, средний)
1. 4,198 сек 2. 4,182 сек 3. 8,646 сек 4. 12,572 сек
При переходе на пхп 7.х ситуация кардинально меняется
1. 1,625 сек 2. 1,612 сек 3. 2,862 сек 4. 13,886 сек
в отличие от 5.6 для пхп 7.х х64 наблюдается ускорение
1. 1,149 сек 2. 1,156 сек 3. 2,871 сек 4. 12,143 сек
отсюда выводы:
вызов функции форматирвоания sprintf очевидный аутсайдер, и это понятно, т.к. переключение стека и т.п. тоже требует приличных ресурсов. х64 версия для 5.6. работает несколько дольше, чем х32, хотя в случае пхп 7.х ситуация обратная и выигрывает х64 вариант. вариант с конкатенацией всегда проигрывает варианту с подстановкой в строку, и если для пхп 5.6 в 1.5-2 раза, то для пхп 7 в 2 раза и более. в пхп 7. варианты 1 и 2 подставноки в строку в двойных кавычках идентичны по скорости, хотя в 5.6 первый несколько проигрывал. пхп 7 в 2.5-3.5 раза быстрее в данных операциях чем 5.6.

Можно ли использовать экран в Андроид полностью?

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


Ответ

Добавьте данную строку в метод onCreate() вашей Activity
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)

Поиск разных частей строки по регулярному выражению

Приведу сильно упрощенный пример. Есть строка str, допустим:
user=123456(somelogin)
Нужно получить идентификатор пользователя и его логин. Сейчас сделал так:
String id = str.replaceAll(".*user=(\\d+).*", "$1"); String name = str.replaceAll(".*user=\\d+\\((.*)\\).*", "$1");
Есть ли универсальный способ сделать это в одно действие, объединив 2 регулярки?
Возможно, так же красиво, как в языках с поддержкой кортежей или деструктуризации, не получится, но меня устроит вариант применения регулярки .*user=(\\d+)\\((.*)\\).* и получения на выходе массива строк, где первый элемент - первая группа, а второй - вторая.


Ответ

Можно воспользоваться связкой Pattern и Matcher. Решение будет не в одну строку, но зато по нему будет понятно, что вы что-то ищете в строке, а не заменой занимаетесь:
String str = "user=123456(somelogin)"; Pattern pattern = Pattern.compile(".*=(\\d+)\\((.*)\\)"); Matcher matcher = pattern.matcher(str); if (matcher.matches()) { String userId = matcher.group(1); String login = matcher.group(2); }

Регулярное выражение рассчитано на представленный пример строки. Если строка, на самом деле, может варьироваться сильнее, то нужно скорректировать рег. выражение. В частности, если в строке могут быть символы после логина (и закрывающей скобки), то нужно либо добавить .* в конец рег. выражения, либо отказаться от .* с обоих концов рег. выражения и метода matches в пользу метода find

QT, C++, Linux и Vim

Недавно решил перейти к изучению С++ и QT (до этого изучал Си) и хотел прояснить несколько вещей для себя. Прошу не ругать меня строго, так как я только-только начинаю: всего-то пока скачал книгу Прата по С++, а про QT знаю только по страничке в Википедии.
Вообщем:
1) Что нужно для программирования с помощью QT на линуксе?
2) Нужен ли для этого обязательно QTCreator?
3) Вопрос вытекает из предыдущих двух: можно ли использовать QT пользуясь vim-ом в качестве редактора, clang-ом для компиляции и make-ом для сборки проектов?
Не то, чтобы я априори не любил IDE, но мне больше нравится другой вариант (чисто субъективно). Программирование для меня просто хобби.


Ответ

Что нужно для программирования с помощью QT на линуксе?
Минимальный набор стандартен: компилятор, редактор, собственно Qt с его инструментами (moc, uic, qmake), хедерами и прочей dev-мишурой и, конечно, собственные знания.
Кроме того желательно:
Высокоуровневая система сборки с поддержкой Qt (можно и вручную писать Makefile'ы, но это дело тем менее благодарное, чем сложнее организация проекта); основные варианты:
qmake, родной, требует минимального изучения, но не универсальный и не очень гибкий cmake, универсальный, требует отдельного (хотя бы минимального) изучения. Autotools — инструмент матёрых GNU'шников. Сложен. Если нет желания прописывать создание формочек в коде, а пользоваться Qt'шным генератором то крайне желателен designer Плагины для редактора в меру своей испорченности. Для автодополнения vim/плюсов хороша будет комбинация YCM+clang+cmake. Отладчик. Если с голым gdb чувствуешь себя комфортно/готов разбираться, то его хватит. Если нет, то придётся пользоваться IDE т.к. нормального лёгкого гуя к нему не существует. Также крайне полезно стащить из kdevelop pretty-printer'ы для Qt.
Нужен ли для этого обязательно QTCreator?
Нет.
Вопрос вытекает из предыдущих двух: можно ли использовать QT пользуясь vim-ом в качестве редактора, clang-ом для компиляции и make-ом для сборки проектов?
Да. С оговорками про make

Ошибка в определении количество элементов массива в C++

// TestLesson.cpp: определяет точку входа для консольного приложения. //
#include "stdafx.h" #include #include using namespace std;
int main() { setlocale(LC_ALL, "rus"); int* size = new int; cin >> *size; cout << "Элементы массива: | "; char* arrayChar = new char[*size]; for (int k = 0; k < *size; k++) { arrayChar[k] = 'a' + k; cout << arrayChar[k] << " | "; } cout << endl; cout << strlen(arrayChar); system("pause>nul"); return 0; }
Почему метод srtlen() выводит отве больше, чем реально заданных (заданных при объявлении)? И при чем не имеер значение какой массив: статический или динамический. Я использую Microsoft Visual Studio 2017


Ответ

Функция strlen предназначена для определения длин С-строк. Аргументом функции strlen может быть только указатель на начало С-строки. В противном случае поведение не определено.
С-строкой называется последовательность символов типа char, завершающаяся символом '\0'. У вас в коде эти требования соблюдены? Нет. Поэтому применение функции strlen в вашем коде вызывает неопределенное поведение. Что вы и наблюдаете.
К "определению количества элементов массива", упомянутому в заголовке вашего вопроса, функция strlen никакого отношения не имеет. Более того, в С++ нет встроенных средств для определению количества элементов массива, выделенного через new [].
В вашем коде вы и так знаете размер вашего массива - это *size. Тщательно берегите этот размер и пользуйтесь им везде, где он вам нужен. Разумеется, вместо "голого" массива вы можете воспользоваться std::vector, который будем сам хранить этот размер для вас.

Как поделить двоичное натуральное на 10 фиксированным количеством сдвигов, сложений и вычитаний?

Умножение на 10 можно представить в виде
x * 10 = x * 8 + x * 2 = (x << 3) + (x << 1)
А можно ли каким-то подобным способом (сдвигами, сложениями и вычитаниями) делить на 10? (Вычитание 10 из x до посинения - не подходит.)


Ответ

Деление беззнаковых целых 32 и 64 разрядных на 10 с возвратом частного и получением остатка.
// http://www.hackersdelight.org/divcMore.pdf uint32_t divu10(uint32_t n, uint32_t *rem) { uint32_t q, r; q = (n >> 1) + (n >> 2); q = q + (q >> 4); q = q + (q >> 8); q = q + (q >> 16); q = q >> 3; // orig: r = n - q*10; r = n - ((q << 3) + (q << 1)); *rem = r > 9 ? r - 10 : r;
// orig: return q + ((r + 6) >> 4); return q + (r > 9); }
uint64_t divu64_10(uint64_t n, uint32_t *rem) { uint64_t q, r; q = (n >> 1) + (n >> 2); q = q + (q >> 4); q = q + (q >> 8); q = q + (q >> 16); q = q + (q >> 32); q = q >> 3; // orig: r = n - q*10; r = n - ((q << 3) + (q << 1)); *rem = r > 9 ? r - 10 : r;
// orig: return q + ((r + 6) >> 4); return q + (r > 9); }
Практически используется для вывода uint64_t на 32-bit микропроцессоре, в котором нет 64-разрядного умножения.

Неиспользуемые переменные

Доброго времени суток!
Подскажите пожалуйста, читаю книгу Герба Саттера, и он пишет такой код:
int a = 10; a; //для подавления предупреждения о неиспользуемой переменной
Вопрос: для чего подавлять это предупреждение? Разве это на что то повлияет?


Ответ

К сожалению, информация в этой книге явно устарела. Подавление предупреждения о неиспользованной переменной (или параметре) путем написания выражения, где кроме этой переменной ничего нет, приведет к появлению предупреждений а бесполезном выражении
Для подавления предупреждения раньше следовало использовать приведение переменной к void: static_cast(a); (обычно обoрачивается в макрос типа UNUSED_VAR). В этом случае никаких предупреждений не последует
В современном С++ появился способ отметить переменную как специально неиспользованную. Для этих целей предусмотрен стандартный аттрибут maybe_unused: [[maybe_unused]] int a = 10;. И в этом случае никаких предупреждений не будет
Подавлять это предупреждение имеет смысл только в одном случае, когда имеется функция, результат который нельзя игнорировать, но мы намеренно хотим это сделать:
[[nodiscard]] int foo(void){ return 0; }
int main() { foo(); // warning: result of foo is not used int a = foo(); // warning: unused variable a [[maybe_unsed]] int a = foo(); // no warnings }

parseInt(null, 24) === 23. Почему?

Каким образом преобразованные в число NaN и 24 трансформировались в 23?
for(var i = 1; i <= 36; i++) console.log(i, parseInt(null, i), parseInt("null", i));


Ответ

Простое совпадение.
parseInt(null, 24)
означает привести строку "null" (строку потому, что первый параметр, переданный parseInt() всегда конвертируется в строку) в число в системе счисления с основанием 24.
"n" в данном случае - 23 (потому что есть 9 цифр (кроме нуля) и "n" - 14 буква алфавита. 9 + 14 = 23).
"u" - 30. Уже выходит за пределы системы счисления с основанием 24. Поэтому возвращается 23, то есть число, полученное до этого момента.
Иными словами parseInt(null, 24) === parseInt("null", 24) === parseInt("n", 24) === 23
Отсюда и ответ - 23 === 23 - true
parseInt(null, m) === 23 всегда даст true, если m находится в пределе от 24 до 30.
Конкретно этот случай интересен лишь тем, что в первый параметр передается null как значение, а не как строка. Это вас и смутило. И null - это, пожалуй, единственное значение в языке, при конвертации в число с основанием 24 которого результат максимально приближен к самому основанию системы счисления.
Каким образом преобразованные в число NaN и 24 трансформировались в 23?
И насчет вот этой части. Это не NaN и 24 "трансформировались", а только null, которое при конвертации в число (с основанием 24+) средствами метода parseInt дает 23.
То есть метод parseInt принимает в качестве первого аргумента то, что нужно сконвертировать, а в качестве второго то, что будет является основанием системы счисления
Больше о самом методе здесь, о "системах счисления" тут (больше по соответствующему запросу в гугле; посмотрите также именно про "основание системы счисления"), другие ответы на этот вопрос (на английском, правда) здесь

Python (jupyter) анимированный график

Подскажите есть ли возможность в jupyter рисовать анимированные графики, вроде графика загрузки процессора в реальном времени? Пытаюсь сделать мониторинг времени ответа сервера на пинг. Разбираюсь с matplotlib, но то ли он такого не умеет, то ли я не нашел.
import subprocess import re from matplotlib import pyplot as plt
def ping(adress): p = subprocess.Popen(["ping.exe",adress], stdout = subprocess.PIPE) out = p.communicate()[0] t = re.search(r'time=(\d*)',str(out)) time = t.group().replace('time=','') if t else '0' return (time)
x=[0]
%matplotlib inline
for i in range(0,10): x.append(ping('ya.ru')) plt.plot(x)
График просчитывается весь и отрисовывается весь сразу, подскажите как сделать анимацию и возможно ли вообще такое?


Ответ

Можно так сделать:
import psutil from datetime import datetime as dt from collections import deque import matplotlib.pyplot as plt from matplotlib.dates import date2num import matplotlib.animation as animation
%matplotlib notebook
N=600 x = deque([date2num(dt.now())], maxlen=N) y = deque([0], maxlen=N)
fig, ax = plt.subplots(figsize=(8,3)) line, = ax.plot_date(x, y, marker="")
ax.spines['left'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False)
def get_data(): # return ping('ya.ru') return psutil.cpu_percent(.15)
def animate(i): x.append(date2num(dt.now())) y.append(get_data()) ax.relim(visible_only=True) ax.autoscale_view(True) line.set_data(x, y) ax.fill_between(x, -0.5, y, color='lightgrey') return line,
ani = animation.FuncAnimation(fig, animate, interval=300) #ani.save("d:/temp/test.gif", writer='imagemagick', fps=10) plt.show()
Результат:

Преобразование текста в path

У меня есть SVG файл с текстом
ПРИВЕТ
Мне необходимо преобразовать текст в path, что бы каждая буква стала путём, как это можно сделать?
JavaScript, редактор, online сервис - подходит любое решение, так как операция разовая.


Ответ

В редакторе Inkscape перевести текст в path можно и так:
выделяем текст; выбираем пункт меню Контур->Оконтурить объект
Результат можно увидеть прямо из программы во встроенном редакторе XML:
выбираем пункт меню Правка->Редактор XML... В нём подсвечивается код XML выбранных объектов.

Убрать switch размером с гору Эверест

В общем, есть switch длиной с Эверест, как бы вы избавились от него, кроме как записывать это в Dictionary?
switch (currencyLeft) { case "BTC": return 0.001m; case "BCH": case "ETH": case "FCT": case "NEO": case "UBTC": case "XEM": case "ZEC": return 0.01m; case "MCO": case "QTUM": case "REP": case "STX": case "VET": return 0.1m; case "ETC": case "DASH": case "LTC": case "XLM": case "XRP": case "XMR": return 0.5m; case "GAT": return 8m; case "BMC": case "DENT": case "DRG": case "ETN": case "FDX": case "FLIXX": case "FSN": case "GZE": case "IND": case "IXT": case "MTN": case "OAX": case "ONG": case "QASH": case "RKT": case "SAL": case "SER": case "SNIP": case "SPHTX": case "STAC": case "STORJ": case "STU": case "TPT": case "TRX": case "VZT": return 1m; default: throw new Exception("Unsupported symbol"); }
UPD: сам switch и так находится в приватном методе, который возвращает decimal и принимает string. Задача в том, чтобы этот код (логику, если так можно "это" назвать) как-то упростить (уменьшить), если это возможно, но не словарем.


Ответ

Хардкод значений и курсов в коде - это нехорошо.
Положите все это в CSV / JSON / базу данных. Т.е. в любое хранилище, кроме кода. Поднимайте из хранилища по первому обращению и десериализуйте в Dictionary

Как SVG сконвертировать в JPG или PNG на C#?

Я генерирую SVG файлы на C#, необходимо используя C# отрендерить их в JPG или PNG. Как это можно сделать?
Интересны любые варианты, но ответом приму только тот который будет работать на shared хостинге, так как скрипт будет запускаться там. Хостинг ASP.NET MVC 5 - Smarterasp


Ответ

Библиотека SVG для C#.
Работает так:
SvgDocument svgDoc = SvgDocument.Open("myFile.svg"); System.Drawing.Bitmap bitmap = svgDoc.Draw(); bitmap.Save("outFile.jpg", ImageFormat.Jpeg);
Брать надо пакет не из NuGet так как там древняя версия и много багов, а прямо горячую, придётся скачать с github и скомпилировать.
Проект рабочий, поддерживается и развивается, но как оказалось присутствуют баги, которые разработчики постепенно убирают.
Библиотека позволяет не только рендерить готовый SVG файл, но и создавать его используя свой API на лету.

Как делать блоки такого вида?


Каким образом лучше всего делать блоки такого вида?
Чтобы при масштабировании форма была адаптивна и текст не выходил за границы блока.


Ответ

Решение SVG
Решение адаптивно, работает во всех браузерах. Текст и знак параграфа находятся внутри блока SVG, поэтому никогда не нарушится их взаимное положение и текст не выйдет за пределы блока при любом изменении размеров окна браузера. Рамки и текст будут изменяться пропорционально.
* { margin: 0; padding: 0; } .container { width: 100%; height: 100%; }

§ TYPOGRAPHY Lorem ipsum dolor sit, amet consectetur adipisicing adipisicing elit Phasellus tincidunt dignissim nibh

Второй вариант блока с тенью
Для реализации тени под первый полигон добавляем второй полигон и смещаем его на 2px вправо и вниз: * { margin: 0; padding: 0; } .container { width: 100%; height: 100%; }
§ TYPOGRAPHY Lorem ipsum dolor sit, amet consectetur adipisicing adipisicing elit Phasellus tincidunt dignissim nibh

В чем разница между loop и while true?

В чем разница между loop и while true в rust?
В документации написано что:
loop {} Интерпретируется по другому компилятором чем:
while true {} Хотел бы понять в чем эта разница и на сколько плохо использовать не loop, а while true
версия вопроса на Английском от @aij


Ответ

На такой вопрос был дан ответ в Reddit.
Разница заключается в том, что в случае while true все переменные должны быть инициализированы до цикла, а в случае loop это не обязательно:
Пример с loop
let x; loop { x = 1; break; } println!("{}", x) этот код отлично работает, однако следующий
let x; while true { x = 1; break; } println!("{}", x); покажет ошибку компиляции "use of possibly uninitialised variable" с указанием на x в println. Во втором случае компилятор не определяет, что тело цикла всегда выполнится хотя бы один раз.
перевод ответа @telotortium

Подсчет ссылок в C++

Как реализовать подсчет ссылок при создании собственного класса C++?
То есть нужен счетчик, который хранил бы количество ссылок, ссылающихся на объект. Если этот счетчик равен нулю, то объект необходимо удалить. Хочется разобраться в этом, но не имею ни малейшей мысли как это реализовать.


Ответ

Простейший вариант - примерно так (это набросок, не более того):
class CountedPtr { ... Type1 p1; // Данные Type2 p2; // Данные .... int * cnt; // Счетчик
В конструкторе - помимо прочего -
cnt = new int(1);
В копирующем конструкторе - cnt копируется и увеличивается на 1. Соответственно обрабатывается присваивание (проще всего его реализовать через идиому обмена с копией). В деструкторе - что-то типа
if (--*cnt == 0) { delete ptr; delete cnt; }
Для начала (и понимания азов) хватит?

Изменить цвет текста, если фоновое изображение не белое?

Я прочитал много статей об этом, но ничего не нашел подходящего, чтобы решить мою проблему.
Возможно ли каким-либо образом изменить цвет текста на основе фонового изображения с помощью JQuery и / или CSS?
Я должен сделать отзывчивый веб-сайт с этими требованиями, но застрял.


Ответ

Можно использовать режим смешивания. Поддержка браузерами такая же. Не применяется к body
body{ margin:0; font-size:50px; font-weight:bold; color:#4cb29c; } div{ background:linear-gradient(to right, #4cb29c 50%,transparent 50%); min-height:50vh; } p{ text-align:center; mix-blend-mode: difference; margin:0; } .circle{ color:#ee82ee; background: radial-gradient(circle at 75% 0px, #fff 35%, rgba(27, 128, 0, 0.6) 35.5%), url(https://picsum.photos/500/800?image=1069) center/cover; }

asdas das safd gfs gsfgsdf sdf sdfs df

asdas das safd gfs gsfgsdf sdf sdfs df


Вызов C# функции из javascript

У меня есть десктопное приложение на WPF, в котором лежит . В него грузится один сервис с сайта, для отображения и работы с картами. В зависимости от логики я через Invoke вызываю там разные javascript функции.
Что делать, если мне надо подписатся на callback событие? Как из javascript вызвать функцию на C#? Все что удалось нагуглить написано для использования в ASP.Net/Silverlight, но как сделать это в обычном десктоп приложении?


Ответ

Самое простое - сделать на С# ComVisible класс и обращаться к нему из JavaScript. Этот класс уже будет обращаться к приложению (через Application.Current).

Посчитать факториал до 1000

Задача № 18 Посчитать факториал до 1000 (ACMP.RU) Задание не проходит по 10 тесту, хотя 1000! считает правильно (проверил первые 20 знаков, сравнивая с Вольфрам Альфа). Второй день ищу ошибку и не могу найти #include
int main(int argc, char *argv[]) { unsigned long int a[6000] = { }, n, b[6000] = { }, t; freopen("INPUT.TXT", "r", stdin); freopen("OUTPUT.TXT", "w", stdout); scanf("%d", &n); if (n < 0) { printf("0"); return 0; } a[0] = 1; for (int i = 1; i <= n; i++) { for (int j = 0; j < 6000; j++) { t = a[j] * i; b[j] = b[j] + t % 100000; b[j + 1] = b[j + 1] + t / 100000; } for (int j = 5999; j >= 0; j--) { a[j] = b[j]; b[j] = 0; } } int i = 5999; while (a[i] == 0) { i--; if (a[i] != 0) printf("%d", a[i]); } i--;
for (int j = i; j >= 0; j--) { if (a[j] / 10000 == 0) printf("0"); if (a[j] / 1000 == 0) printf("0"); if (a[j] / 100 == 0) printf("0"); if (a[j] / 10 == 0) printf("0"); printf("%d", a[j]); } } Заранее спасибо всем, кто откликнется. Задачу решил с помощью Java из-за того, что в яве не нужно парится с длинной арифметикой. Вот код: import java.math.BigInteger; import java.io.*; import java.util.Scanner;
/** * * @author StalinZ */ public class Main { public static void main(String[] args) throws FileNotFoundException { new Main().run();
} PrintWriter pw; Scanner sc;
private void run() throws FileNotFoundException { sc = new Scanner(new File("input.txt")); int a=sc.nextInt(); pw = new PrintWriter(new File("output.txt")); BigInteger ret =BigInteger.ONE ; for (int i=1;i<=a;i++) ret = ret.multiply(ret.valueOf(i)); pw.print(ret.toString()); pw.close(); } } Правда я заметил, что ява жрёт больше памяти


Ответ

Только что решил задачку сам, проверил, получил accepted. Конкретно ваша программа, например, фейлится на тесте n = 999 и выводит один лишний ноль. Почему это происходит, подсказывать не буду, думаю вам самому интересно будет разобраться. Если что, то мое решение можно посмотреть на pastie.org

Программирование под Linux

Не так давно я начал изучать C/C++, сейчас я уже достаточно хорошо себя в нём чувствую и хотелось бы уже поработать с ОС, а именно с Linux. С самим Linux я знаком не сильно, но по ходу обучения буду осваивать систему с точки зрения программиста. Сейчас стоит Ubuntu, поставил g++, исходники компилируются, всё хорошо. Основной упор делается на системное и сетевое ПО. Собственно нужна литература на русском, т.к англйиский не на уровне чтобы учить программирование к сожалению, нужно что нибудь для новичков.
Выбор велик, не хотелось бы читать плохую литературу.


Ответ

Для начала могу порекомендовать очень хорошую книгу Метью, Стоунс "Основы программирования в Linux". С нуля обо всем в достаточно приличном объеме. Для начала самое пригодное.

Расскажите про Python [закрыт]

Хотел бы узнать немного про Python, препод очень рекомендовал. Что за язык, какие особенности, да и вообще мнение тех кто уже пишет или писал на нём. Также неплохо бы и хорошие ссылки.


Ответ

Язык очень хорош тем, что позволяет быстро писать рабочие программы. Иногда целые листинги программ таких языков как Java, C++, C# можно заменить всего одной аналогичной строкой на питоне. Помню писал давно программку решения судоку: функция принимающая массив исходных данных и возвращающая ответ состояла из 30-40 строк кода. Язык очень краток и красив. Это основное за что я его люблю. Высокая читаемость кода, его организация иерархии при помощи отступов изначально учит оформлять код. Портируемость на очень высоком уровне. Питон существует наверно для всех платформ. Большое количество модулей позволит не изобретать велосипед Обьектно-ориентированность. Все в питоне является объектами. python.org Стоит набрать в поиске учебник питон, и Вы тут же увидите кучу хороших учебников. UPD Простота. Его конструкции очень просты и понятны. Как пример приведу срезы массивов arr[5:10] (срез от 5 до 10 элемента), arr[5:] (от пятого элемента до конца), arr[:-5] (от начала до 5 элемента с конца). И впомните как добиться аналогичного эффекта в других языках.

Полупрозрачный фон виджета в QT

Необходимо сделать фон виджета QLabel полупрозрачным. Подскажите, как это можно реализовать? opacity использовать не получается, т.к. оно может использоваться только в всплывающих окнах.


Ответ

Надо расширить класс QLabel и в новом классе переопределить метод paintEvent, вставив туда примерно такой код QPainter paint; paint.begin (this); paint.setBrush (QBrush (QColor (255, 255, 255, 180))); paint.setPen (Qt::NoPen); paint.drawRect (0, 0, width(), height()); paint.end(); В QColor последнее значение - значение альфа-канала, которое и определяет прозрачность. Меняется от 0 (полностью прозрачное) до 255.

Как отправить POST запрос в jQuery Ajax в CP1251?

Есть форум IPB 2.3.6 с кодировкой cp1251. Надо запостить сообщение в тему. Вот код: (function NewPost(fid, tid, auth_key) { var ajaxUrl = 'http://example.com/index.php?'; var text = "Тестовый пост"; var baseData = { act: "Post", CODE: "03", f: fid, t: tid, auth_key: auth_key, Post: text}; var jqxhr = jQuery.ajax({ type: "POST", data: baseData, dataType: "html", contentType: 'application/x-www-form-urlencoded; charset=windows-1251', url: ajaxUrl }) jqxhr.done( function(data) { console.log('Новое сообщение создано') }) jqxhr.fail( function(err) { console.log(err) }) }) (227, 11764579, '17cc48183ae68447d8836f40932ba4e4') В результате на сайте выводится текст на UTF -> каракули. Как решить проблему без изменений на сервере - форум не мой.


Ответ

Никак. AJAX-запросы передаются только в UTF-8

Преобразовать список сессий во временной ряд

Есть сырые данные истории использования объектов в виде списка сесстй-троек (id объекта, время начала, время окончания) [(1, "2012-09-20 00:00:00+04", "2012-09-20 05:00:00+04"), (1, "2012-09-20 07:30:00+04", "2012-09-20 09:25:00+04"), (2, "2012-09-20 07:00:00+04", "2012-09-20 09:15:00+04")] Т.е., в данном примере объект 1 использовался дважды, с 00:00 по 05:00 и с 07:30 по 09:25, а объект 2 — с 07:00 по 09:15. Список сейчас отсортирован по ID объекта и потом по возрастающему времени, но можно подать данные в любом виде — в общем-то, это таблица в SQL'ной RDBMS. Записи как правило, не должны, но, теоретически, могут пересекаться — т.е., может случиться так, что будет [(1, "…", "… 12:00:37"), (1, "… 11:59:42", "…")], и в этом случае можно считать, что использование в районе 12 часов не прерывалось. Хочу получить из такого списка временной ряд, условно, следующего вида: [("2012-09-20 00:00:00+04", {1}), ("2012-09-20 05:00:00+04", {}), ("2012-09-20 07:00:00+04", {2}), ("2012-09-20 07:30:00+04", {1,2}), ("2012-09-20 09:15:00+04", {1}), ("2012-09-20 09:25:00+04", {})] Т.е. с 00:00 (минимальная дата-время в истории) использовался объект 1, потом в 05:00 ничего, потом с 07:00 — объект 2, затем оба объекта, и т.д., до 09:25, на которое данные закончились. Подскажите, пожалуйста, хороший алгоритм и структуры данных для быстрого выполнения такого преобразования. Объемы — до 10000 объектов, за сроки различной продолжительности (сутки, неделя, месяц, 3 месяца, 6 месяцев, год, больше не интересно), до 100000 записей в сутки. Процессорного времени жалко, памяти — сколько угодно, в физически разумных пределах. Очевидный «жадный» алгоритм с пробегом по временному интервалу не годится — алгоритм не должен напрямую зависеть от продолжительности рассматриваемого интервала, только от количества записей в истории.


Ответ

В такой формулировке, если я правильно все интерпретировал, то звучит как типичный use case для структуры данных под названием Interval Tree. Алгоритм может выглядеть примерно следующим образом:


Нестрогое обоснование и оценка сложности алгоритма:
Понятно, что изменение множества текущих выполняемых объектов может произойти только в момент start или end для некоторой тройки, поэтому подход с UNIQUE должен сработать. Время работы для n входных элементов будет равно O(n log n) + O(n) + O(n * (log n + k)) = O(n * (log n + k)), где k - это количество элементов с пересекающимися интервалами, поскольку сложность вставки составляет O(log n), а стоимость запроса - O(log n + k) Алгоритмическую сложность операций для Interval Tree я подсмотрел здесь.
В свое время пользовался boost::icl для схожих целей.

Что такое CGI?

Извините возможно за столь тупой вопрос но подскажите пожалуйста что такое CGI? С вики статью прочитал ничего не понял. И что значит PHP установлен как CGI?


Ответ

И что значит PHP установлен как CGI? Это значит что хостинг не может сделать нормальную настройку php и привязать её к апачу. в каждом скрипте придется указывать #!/usr/local/bin/php чтобы все это безобразие заработало. Лучше привязка php к апачу как модуль. тут почитать немного И что тут непонятно написано? Последний вопрос, зачем тебе это нужно если ты не понимаешь этого? Просто ради "Чтобы знать!" или есть какие-то еще варианты?

Компиляция нескольких Android приложений из одного исходного кода

Здравствуйте! Мне нужно скомпилировать два разных приложения из одного исходного кода. Эти приложения отличаются только package name и ресурсами. Я хотел использовать аналоги #ifdef #define , но оказалось, что их попросту нет... Конкретнее - мне нужно что бы в одном и том же файле исходников в случае компиляции приложения использовался файл ресурсов(R) одного приложения, а для другого приложения - другой файл.


Ответ

Все очень даже реально. Есть такой проект - antenna, он формально реализовывает препроцессор. Почитать как сделать и что скачать, можно на хабре В нескольких проектах испытывал, достаточно нормально работает.

Авторизация Вконтакте не работает


aaa

".$obj['error'].":".$obj['error_description'].$obj['access_token']); echo("

code:".$_SESSION['code']); ?> Вот, это мой код для авторизации Вконтакте, я запрашиваю ключ, гет запросом его мне возвращают. Всё верно, ключ видно, всё работает. После этого я делаю запрос с ключем(джейсон) с целью получить токен. В случае если токен есть выводится токен на экран, если его нет выводится сообщение об ошибке. У меня не разу за весь день не получилось подцепить токен. Выдаёт следующее: invalid_grant:Code is invalid or expired. Что делать подскажите. Всё АПИ настроено, сайт зареган, секретный ключ получен. Что не так? Не понимаю


Ответ

$app_id = "*****"; $app_secret = "******************"; $my_url = "http://*****.com/oauth/vk.php";
session_start();
$code = $_REQUEST["code"];
if(empty($code)) { $dialog_url = 'http://api.vkontakte.ru/oauth/authorize?client_id='.$app_id.'&scope=offline&redirect_uri='.$my_url.'&response_type=code'; echo(""); } else { $token_url = 'https://api.vkontakte.ru/oauth/access_token?client_id='.$app_id.'&client_secret='.$app_secret.'&code='.$code.'';
$params = json_decode(@file_get_contents($token_url));
print_r($params);
$graph_url = 'https://api.vkontakte.ru/method/getProfiles?uid='.$params->user_id.'&access_token='.$params->access_token.'&fields=photo,nickname';
$user = json_decode(@file_get_contents($graph_url)); $userResponse = $user->response[0];
if ($userResponse->uid != '') { print_r($userResponse); echo ('Вы успешно авторизованны через вКонтакте'); } else echo('Ошибки авторизации!'); }
?>

Структура базы данных для простой CRM

Сразу оговорюсь, что я еще совсем начинающий, поэтому просьба не обижать. Есть задача - написать простейшую CRM-систему, с функциями добавления, удаление, сортировки задач и различными несложными фичами. В системе будет 3 уровня (задачи, подзадачи и подподзадачи). Собственно, вопрос вот в чем - как мне организовать структуру базы данных - создавать для каждого уровня отдельную таблицу, связанную с остальными?


Ответ

users - id, login, (name, password) tasks - id, parent_id, description, status, (name, time, deadline, date_created) task_user - user_id, task_id В скобках - необязательные поля.

Оцените, пожалуйста, мою верстку [закрыт]

http://websterjoy.tk/ Впервые сверстал на html5, как скажете? правильно ли все, семантично ли? Какие замечания вы могли бы сказать по поводу верстки? CSS разумеется валидацию не проходит, т.к вендорные префиксы и т.д.


Ответ

Моё мнение, которое не претендует на истину. По поводу семантичности: Вы слишком увлеклись тэгом section, в большинстве случаев можно было спокойно использовать div Для тэга header главного для страницы, рекомендуется использовать класс, например .page-header и уже от него настраивать разметку его содержимого. По поводу самой вёрстки: Не используйте классы типа .gray, .green, .black2 и т.д. Название класса должно быть осмысленным. То же самое касается и классов типа fs12, fs14, fs16. Их можно переименовать например в font-size-small, font-size-medium и т.д. Т.к. вы используете на сайте чаще размер шрифта в 12px, то можно, например, такой размер задать по умолчанию для body и тогда код станет чище. Забудьте про

, используйте .clearfix Не используйте h3 для вывода цены и h1 для количества упаковок, который у вас по счёту вторым получается, что недопустимо. Сеошники могут и побить :) Маленькие картинки объедините в sprite ( спрайты ) Нет смысла использовать float с display:inline-block т.к. float делает элемент блочным (т.е. display:block). Определитесь с поддержкой браузеров, а то для border-radius вы поддерживаете аж FF 3.6 c префиксом -moz, хотя не делаете того же для box-shadow ( класс .show_current ) я надеюсь вы используете @import только при разработке, а потом всё равно стили склеиваете. Если что-то ещё замечу, обновлю пост.

Упорядочивание (не сортировка!) массива по индексу

Подскажите, пожалуйста, как упорядочить массив по индексу следующим образом: Из: [0] => длодлодо ... [1] => фываыва. [4] => sdfsadfsa. [6] => Оsdfgdfg .... [7] => sdfgdfg- ... [9] => вапвап в: [0] => длодлодо ... [1] => фываыва. [2] => sdfsadfsa. [3] => Оsdfgdfg .... [4] => sdfgdfg- ... [5] => вапвап В мануале подходящего ничего не нашел. Надеюсь, что упустил нужную функцию и вы мне её подскажите. А то придется изобретать велик. Спасибо.


Ответ

$new_arr = array_values($old_arr); Код на ideone.com

Boxing in Java

Добрый день. Читаю , про автоупаковку в Java и появился вопрос : Integer i0 = 100; Integer i1 = new Integer(100); System.out.println(i0 == i1); Почему результат false ? Ведь , если сделать так : Integer i0 = 100; Integer i1 = 100; System.out.println(i0 == i1); То результат будет true. Хотя в первом примере строка : Integer i1 = new Integer(100); Где значение 100 тоже упаковывается, но только вручную, а не автоматически (как во втором примере) в объект типа Integer.


Ответ

Такой код Integer i0 = 100; эквивалентент такому: Integer i0 = Integer.valueOf(100); Если взглянуть на реализацию метода valueOf, то можно увидеть, что для значений от -128 до 127 используется кэш объектов типа Integer. См. так же документацию метода valueOf При вызове же конструктора кэш не используется и создается новый экземпляр класса Integer

Как быть с новым стандартом C++11? [закрыт]

Сейчас пользуюсь 98/03 и стараюсь не обращать внимание на 11, но мне особо и не приходилось, так как ещё не сталкивался с чем-то, что навязывало бы его. А как у вас обстоят дела? Вы уже наверняка видели как многие используют новый стандарт. Что вы думаете по этому поводу? Есть ли смысл в этом, ведь в бусте и так почти все было. С каким багажом знаний с предыдущего стандарта можно переходить на новый? Так же поговаривают о следующем стандарте в 2014 году. Хоть разорвись).


Ответ

Перейти рано или поздно придется. Проблема в том, что еще не все используемые копмиляторы в достаточной мере поддерживают новый стандарт, а в поддерживающих можно найти баги. Я, например, нашел в gcc4.7 баг в std::regexp, причем то же в boost::regexp работало нормально. Но рано или поздно все устанаканится и станет обычным делом, как уже было с с++2003. Так что учить надо, а вот использовать в реальных проектах, особенно для кого-то, где требуется надежность, я бы пока не стал. А для себя, в виде эксперимента - пожалуйста.

Как хранить изображения в готовой базе SQLite

Есть готовая база данных, необходимо в ней хранить изображения (Порядка 1000 картинок, около 40кб каждая). Рето Майер пишет, что лучше в базе хранить ссылки на картинки, а сами картинки отдельно. Но как я понял, готовые картинки в любом случае надо будет хранить где-то в приложении, например в assets, чтобы потом их можно было скопировать на SD карту. Хочется минимизировать размер приложения во внутренней памяти телефона. Как мне оптимизировать решение этой проблемы? Пока вижу 2 выхода, либо хранить в базе, либо в assets


Ответ

Храните картинки на сервере(сайте). Есть например сайт parse.com специально сделанный для упрощения создания клиент-серверных мобильных приложений. Там можно хранить и картинки и бд и все что угодно. Думаю это самое то если их 1000. Если картинок мало, то можно положить и в assets или raw, но конечно смотря какого они разрешения, то бишь размера. А хранение в базе картинок как бинарников врят ли решит проблему. База все равно копируется вместе с данными приложения в память, то бишь от ее разбухания никуда не деться. Не говоря уже о том, что готовые картинки врят ли стоит хранить в БД :)

Выход из приложения как у cleanmaster android

Как реализовать выход из андроид приложения как у клин мастера. После нажатия кнопки back Вылезает Toast "нажмите еще раз для выхода"


Ответ

private static long back_pressed;
@Override public void onBackPressed() { if (back_pressed + 2000 > System.currentTimeMillis()) { super.onBackPressed(); } else { Toast.makeText(getBaseContext(), "Нажмите еще раз для выхода", Toast.LENGTH_SHORT).show(); }
back_pressed = System.currentTimeMillis(); }

Sqlite игнорировать регистр в условии WHERE

Подскажите как на андроиде в sqlite базе сделать выборку на кирилице, игнорируя регистр? запросы с LIKE, COLLATE NOCASE и UPPER(column_name) работают только для английских букв! А для русских нет! Для примера, имею таблицу favourite с записью title = Тест, юзер пытается запросить её но в поле поиска вводит слово тест маленькими буквами. пробовал такие варианты: SELECT * FROM favourite WHERE title LIKE '%тест%' SELECT * FROM favourite WHERE UPPER(title) LIKE UPPER('%тест%') SELECT * FROM favourite WHERE title LIKE '%ТЕСТ%' COLLATE NOCASE все три варианта не подходят, больше ничего не нагуглил. Подскажите пожалуйста решение ps: запросы осуществляю так: SQLiteDatabase db = getWritableDatabase(); //*extends SQLiteOpenHelper* Cursor cursor = db.rawQuery(sql, null);


Ответ

Вообще-то это известный баг или фича (кому как) SQLite. Он не понимает case-insensitive where/like/glob, когда символы не в ASCII. Как говорит мануал: A bug: SQLite only understands upper/lower case for ASCII characters by default. The LIKE operator is case sensitive by default for unicode characters that are beyond the ASCII range. For example, the expression 'a' LIKE 'A' is TRUE but 'æ' LIKE 'Æ' is FALSE.) Единственный способ обойти это ограничение, это завести хранимую процедуру выполняющую операцию сравнения. Update Я слегка погорячился по поводу хранимых процедур в SQLite. SQLite не поддерживает хранимые процедуры в общепринятом смысле, нужно писать т.н. custom function на С, пример здесь

Пишут ли на С++ под iOS и Windows Phone?

Знаю,что под Android пишут. А у iOS и Windows Phone есть аналог NDK, или если писать, то исключительно на ObjC и C#?


Ответ

Пишут.

Достаточно распространено в мобильном геймдеве, например. В играх намного меньше привязка к API системы, а вот сохранить общий код для кучи разных платформ - бесценно. Примером подобного может служить опенсурсный игровой движок cocos2d-x.

На iOS все очень просто и удобно: C++ спокойно сосуществует в одном проекте и даже в одном файле с Objective-C. Возможно использовать как C++ из кода Objective-C, так и наоборот. Все стандартные библиотеки Objective-C могут быть доступны из C++. Естественно, есть некоторые тонкости, связанные с именованием файлов и подключением заголовочных файлов,а так же с памятью, так как в Objective-C есть сборка мусора, а в C++ нет, но, в целом, это мелочи, разработка достаточно проста и удобна. Не уверен, возможно ли это со Swift.

Под Windows Phone я напрямую не разрабатывал. Насколько мне известно из общения с WinPhone-программистами, чистый C++ там нужно подключать к проекту в виде динамической библиотеки (.dll) со всеми вытекающими проблемами. При этом, саму программу можно писать на C++/CLI (managed C++).

В сравнении с Android разработкой:
Разработка под iOS на C++ в разы удобнее. Под WinPhone я бы сказал - примерно сопоставима по проблемам, но эти проблемы в корне различны.

Как создать jar-архив используя (в) Intellij idea?

Не могу создать создать исполняемый архив JAR .Как я понял данная проблема должна решаться с помощью Terminal ,НО ОН У МЕНЯ И НЕ РАБОТАЕТ(не могу туда заносить текст,как и печатать там ,так и вставлять туда скопированный текст).Также как использовать при компиляции флаги.Также где набирать команду для создания jar-архива?


Ответ

В идее сначала идете в File | Project Structure | Artifacts, там создаете новый artifact, jar --> From modules with dependencies
Потом Build | Build artifacts

Нахождение меньшего числа из трех

Здравствуйте, есть файл с исходными данными:
-1 -2 -3 -4 -5 -6 -7 -8 -9
нужно сравнить числа построчно и найти меньшее:
f=open('input.txt','r') for i in range(3): a,b,c=f.readline().split() print(a,' ',b,' ',c) if a

Нужно ли удалять ветку после слияния её с другой?

В проекте есть ветка master. От нее ответвлена dev, а от dev идут ветки отдельных фиксов, назовем fix Т.е. проект выглядит как master -> dev -> fix. После объединения веток dev и fix, в репозитории сохранилась ветка fix
git checkout dev git merge master <<тут изменения при слиянии>> git branch > fix >*dev > master
Надо ли ее удалять или она так и должна висеть там?


Ответ

Можно вполне спокойно удалить. Многие так и делают, что бы просто не мозолило глаза в списке веток.
Тем не менее, это совершенно не обязательно - если не хотите, можете и оставить.
Ну и естественно не стоит удалять постоянные ветки, которые в команде условлено использовать для постоянного процесса разработки, например созданные для соответствия тому-же Gitflow Workflow. Т.е. если вы скажем, влили ветку develop в master, закончив работу над некой функциональностью, то постоянно удалять ветвь develop после слияния - крайне глупая затея.

Conditional Variables в Windows XP

При запуске программы в Windows XP вылезает окошко с сообщением:
Точка входа в процедуру InitializeConditionVariable не найдена в библиотеке Kernel32.dll.
Чем лечить?
Доступ к коду программы есть, могу написать функцию, реализующую тот же функционал, используя SetEvent(). Как сделать, чтобы в зависимости от ОС вызывалась та или иная функция? На мой взгляд, это самое простое решение.


Ответ

Сделать обертку для condition variable (если ее еще нет), а функцию InitializeConditionVariable вызывать через GetProcAddress, а если ее нет, использовать аналоги
Правда, как утверждают разработчики Chromium, сделать правильную реализацию CV под WinXP тяжело, и оно будет работать не быстро. Можете посмотреть на github
Они используют GetProcAdress для получения функций и идиому pimpl для выбора той или иной реализации (для Vista или XP)

вычислить последовательность

n = 12 должно вывести 1+2+3+4+5+6+7+8+9+(1+0)+(1+1)+(1+2) Написал 2 программы, но пишет, из-за того что долго выполняются - процесс отменяется. То есть, их нужно оптимизировать, только вот КАК Код двух программ:
using System;
public class TwistedSum { public static long Solution(long n) { int res = 0; int ostatok = 0; int Part = 0; for (int i = 1; i <= n; i++) { if (i >=10) { Part = i; while (Part >= 0) {
ostatok = Part % 10; Part = Part / 10; res = res + ostatok; } } else { res = res + i} }
return res; } }
(тут передается в n число, все нормально, просто только функция написана) 2ой код:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace codewarsSumaCifr { class Program { static void Main(string[] args) { long n = 10; Console.Write(Solution(n)); Console.ReadKey();
}
public static long Solution(long n) { int res = 0; string str2 = ""; for (int i = 1; i <= n; i++) { str2 = str2 + i.ToString(); }
for (int j = 0; j < str2.Length; j++) { res = res + (int)Char.GetNumericValue(str2[j]);
} return res; } } }


Ответ

Цикл, вообще не правильное решение, его надо свернуть, и решить задачу аналитически. Решать задачу целиком скучно, но идею, как она решается, подкину:
9: (0+0)+(0+1)+(0+2)+(0+3)+(0+4)+(0+5)+(0+6)+(0+7)+(0+8)+(0+9) = 45 19: (1+0)+(1+1) ... +(1+8)+(1+9) + 45 = 1*10 + 1*45 + 45 29: (2+0)+(2+1) ... +(2+8)+(2+9) + 2*45 + 1*10 = 2*10 + 1*10 + 2*45 + 45 ... 99: (9+0)+(9+1) ...+(9+9) + 9*45 + 8*10 ... + 1*10 = 9*10 + 8*10 ... + 1*10 + 9*45 + 45

Как правильно использовать Retrofit library?

Мне необходимо спроектировать Rest Api приложение. В интернете, в том числе в официальной документации показаны примеры использования данной библиотеки выполняя запросы напрямую из Activity, но это ведь неправильно?! Сетевые запросы нужно выполнять с помощью Service?! Как правильно это сделать c помощью Retrofit? Не хочу выдумывать свой "Велосипед".


Ответ

В официальной документации делается акцент на то, чтобы показать как использовать данную библиотеку, а не на то как лучше спроектировать приложение.
Я, например, использую связку retrofit+rxjava+eventbus и работаю по следующей схеме: методы ретрофита возвращают Observable вокруг которого я начинаю "накручивать" логику(запрос к серверу в отдельном потоке,обработчик ошибок, действия над результатом, обработчик успешного результата). В конце отправляю событие с флагом успешно ли прошел запрос или произошла какая либо ошибка. В итоге код выглядит следующим образом

public class RestInteractionWorker {
RestServerInterface restInterface;
public RestInteractionWorker(){ //создаем объект RestServerInterface }
public void perfomServerOperation(){ restInterface.perfomOperation(...) .subscribeOn(Schedulers.newThread()) //для запроса используем отдельный поток .timeout(30, TimeUnit.SECONDS) // таймаут .map(new Func1() { @NonNull @Override public ActionEvent call(T someModel) {
// обрабатываем результат, после чего высылаем событие с флагом успешного выполнения запроса return event; } }) .onErrorReturn(new Func1() { @NonNull @Override public ActionEvent call(Throwable throwable) { // произошла ошибка, создаем событие сообщающее об ошибке return new TownsTemperatureUpdateEvent(false); } }) .observeOn(AndroidSchedulers.mainThread()) // дальше код будет вызываться в главном потоке приложения .subscribe(new Action1() { @Override public void call(ActionEvent event) { EventBus.getDefault().post(event); // высылаем событие } }); } }
Интерфейс запросов к серверу выглядит так:

public interface RestServerInterface {
@GET("/...") Observable perfomOperation(...); }
Вместо T надо указать конкретный тип, который будет возвращен.
Данную модель я использую когда надо получить данные сервера и сохранить их в базу данных, после чего в приложении отобразить новые обновленные данные. В методе map(...) я сохраняю данные в бд, и возвращаю из него event с флагом успешной загрузки и сохранения данных, после чего в методе subscribe(...) высылаю это событие. В дальнейшем это событие перехватывает тот кто на него подписан и обновляет данные.
Метод onErrorReturn(...) перехватывает все исключения которые произошли во время выполнения.
Если не нужно сохранять данные в бд, а, например, сразу выслать модельный объект, то метод map(...) можно не реализовывать.
Классы событий выглядят примерно следующим образом:

public class ActionEvent {
private final boolean isSuccessefull; private final String message; //можно передавать дополнительную информацию
public ActionEvent(boolean isSuccessefull, String message) { this.isSuccessefull = isSuccessefull; this.message = message;
public boolean isSUccessefull() { return isSUccessefull; }
public String getMessage() { return message; } }
В активити/фрагменте обрабатываю события так:

public void onEvent(ActionEvent event) {
//обработка результата
}
public void onResume(){ EventBus.getDefault().register(this); // подписываемся на прием событий super.onResume(); }
public void onPause(){ EventBus.getDefault().unregister(this); // отписываемся от получения событий super.onPause(); }
Новичку данная модель может показаться сложноватой из-за использования библиотеки rxJava, но в целом для меня это довольно успешная модель реализации взаимодействия приложения с сервером.
Refrofit можно так же использовать в связке с Robospise. В ней как раз все запросы выполняются через Service. Пример можно найти в их репозиторие.

Возможно ли через git копирование на внешний жесткий диск

Хочу организовать домашние хранение исходников. И интересует следующий вопрос:
Могу ли я настроить git таким образом, что бы он работал с github и внешним жестким диском (или флешкой) одновременно. При этом жесткий должен выступать своего рода бэкап хранилищем с которого можно обычным копированием взять любую сохраненную версию.
Например если я проталкиваю изменения, то на жестком в определеной папке создается папка (а еще лучше сжатый архив) с именем проекта и датой внесения и в это папку (или архив) заносится полная копия текущей версии проекта.
PS: В git я новичок, поэтому вопрос может быть банальным, но меня интересует возможно ли это в принципе сделать именно средствами git.
Если это возможно сделать, то буду признателен если напишете приблизительно описание как это можно реализовать.
Операционка - windows.


Ответ

Лучший способ делать бэкап репозитория Git — это репозиторий Git (как ни странно).
Копировать в архивы и папки — плохо и неэффективно. Во-первых, вы таким образом ломаете всю идею и делаете очень неудобные в использовании бэкапы. Во-вторых, Git очень эффективно хранит свои данные и простой архив вам такой эффективности не предоставит.
Предлагаю такой способ: сделать локальный bare репозиторий и обновлять в него.
Делаем резервную копию
Пример: репозиторий у нас лежит в ~/repo. Резервную копию мы будем создавать в ~/backup.
$ mkdir ~/backup $ cd ~/backup $ git clone --mirror --no-hardlinks ~/repo
После этого в папке ~/backup/repo.git будет создан bare-репозиторий. Обратите внимание, что папка не просто .git, а repo.git. Параметр --mirror делает следующее.
Включает в себя параметр --bare — cделать репозиторий голым (bare). Такой репозиторий хранит только файлы Git и не хранит обычные файлы в рабочей области (в резервной копии они нам не нужны) Заставляет Git копировать все ветки (branches), метки (tags) и другое. Подробнее в документации
Параметр --no-hardlinks нужен для того, чтобы Git не пытался сэкономить место, делая хардлинки вместо прямого копирования файлов. Для резервной копии хардлинки не годятся.
Обновляем резервную копию
Теперь мы можем подключить эту резервную копию как remote и в нее делать push.
$ cd ~/repo $ git remote add backup ~/backup/repo.git $ git push backup --all
Либо заходить в папку резервной копии и там делать update
$ cd ~/repo $ git --git-dir=~/backup/repo.git remote update
Параметром --git-dir мы явно указываем Git, где искать его директорию. Сам не найдет, т.к. имя нестандартное.
Восстанавливаемся из резервной копии
Разумеется, для этого понадобится Git. Если совсем нет возможности его установить, попробуйте Git Portable от sheabunge.
Вместе с репозиторием
обычным копированием взять любую сохраненную версию.
Чтобы достать сохраненную версию из нашего резервного репозитория:
cd ~/new-repo git clone ~/backup/repo.git . git pull --all
Теперь у нас есть полная копия того репозитория + версия рабочей области из последнего коммита в master. Можем получить любое другое сохраненное состояние:
git checkout
Только файлы из резервной копии
git --git-dir=~/backup/repo.git --work-tree=куда/положить/файлы checkout
Параметр --work-tree указывает Git путь, который он будет считать своей рабочей областью на время выполнения текущей команды. Путь должен существовать (т.е. Git не будет создавать его сам).
Только файлы из рабочего репозитория
cd ~/repo git --work-tree=куда/положить/файлы checkout
Git просто скопирует текущее состояние рабочей области туда, куда нужно.

Замена объекта из массива

Есть массив из фото (из 25 штук):
private int[] image_res = {R.drawable.res_null, R.drawable.res_null, R.drawable.res_null}
Пытаюсь заменить фото на другое фото. Использую image_res.set(2, R.drawable.rees_ok); но пишет
cannot resolve method set (int, int).
Какую ошибку я допускаю?


Ответ

Так у Вас же массив, а не коллекция.
Установка значения в массив происходит так:
image_res[2] = R.drawable.rees_ok;

Как в C# реализовано создание string из строки в кавычках?

Если я пишу в коде строку в двойных кавычках, она сразу становится безымянным экземпляром типа string, а значит я могу поставить в конце точку и использовать методы со строкой. Если поставлю символ в одинарных кавычках - это будет char. А как мне реализовать что-то подобное со своим классом? Ну например если я что то возьму в кавычки, перед которыми будет символ звездочка (или просто в звездочки), то чтобы создавался экземпляр класса MyClass?


Ответ

То, что вы просите - это литералы для пользовательских типов. К сожалению, все поддерживаемые типы литералов жестко прописаны в стандарте языка.
Но вместо них (в какой-то мере) можно использовать implicit-операторы. Например:
public class MyClass { public string Prefix { get; set; } public string Suffix { get; set; }
public static implicit operator MyClass(string source) { var tokens = source.Split(':'); return new MyClass { Prefix = tokens[0], Suffix = tokens[1] }; } }
позволяет создавать объекты класса как:
MyClass val = "a:b";
Console.WriteLine(val.Prefix); // a Console.WriteLine(val.Suffix); // b

Как правильно умножить матрицу на другую матрицу в нескольких потоках?

Моя задача такая. Мне нужно параллельно на 8 потоках умножить матрицу 200x248 на матрицу 248x333. В интернете я нашел простой пример умножения двух матриц 4x4 на 4 потоках, но я не совсем понимаю логику разделения этой задачи между потоками. Почему у каждого потока разные границы циклов и как они вообще образовываются? Почему в каждом потоке аж 3 цикла, а не 2? Можете мне объяснить алгоритм, чтобы я мог по его аналогии сделать умножение огромных матриц на 8 потоках?
Вот часть этого кода (там еще есть ввод данных с файла и вывод результата в другой файл, графический интерфейс и другое, но это не столь важно в этом вопросе).
Инициализация статических полей:
public static int[][] a; public static int[][] b; public static int[][] c;
Где-то в main создаются и запускаются потоки:
c = new int[a.length][b[0].length];
Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); Thread3 thread3 = new Thread3(); Thread4 thread4 = new Thread4();
thread1.start(); thread2.start(); thread3.start(); thread4.start();
try { thread1.join(); } catch (InterruptedException e) { e.printStackTrace(); }
try { thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); }
try { thread3.join(); } catch (InterruptedException e) { e.printStackTrace(); }
try { thread4.join(); } catch (InterruptedException e) { e.printStackTrace(); }
Код четырех потоков:
public static class Thread1 extends Thread {
@Override public void run() { int m = a.length; int n = b[0].length; int k = (a.length) / 4;
for (int i = 0; i <= k; i++) { for (int j = 0; j < n; j++) { for (int l = 0; l < b.length; l++) { c[i][j] = c[i][j] + a[i][l] * b[l][j]; } } } } }
public static class Thread2 extends Thread {
@Override public void run() { int m = a.length; int n = b[0].length; int k = (a.length) / 2 + 1; int s = ((a.length) / 4) + 1;
for (int i = s; i < k; i++) { for (int j = 0; j < n; j++) { for (int l = 0; l < b.length; l++) { c[i][j] = c[i][j] + a[i][l] * b[l][j]; } } } } }
public static class Thread3 extends Thread {
@Override public void run() { int m = a.length; int n = b[0].length; int k = ((3 * (a.length)) / 4) + 1; int s = (a.length) / 2 + 1;
for (int i = s; i < k; i++) { for (int j = 0; j < n; j++) { for (int l = 0; l < b.length; l++) { c[i][j] = c[i][j] + a[i][l] * b[l][j]; } } } } }
public static class Thread4 extends Thread {
@Override public void run() { int m = a.length; int n = b[0].length; int k = ((3 * (a.length)) / 4) + 1;
for (int i = k; i < m; i++) { for (int j = 0; j < n; j++) { for (int l = 0; l < b.length; l++) { c[i][j] = c[i][j] + a[i][l] * b[l][j]; } } } } }


Ответ

Полная тестовая программа, вычисляющая произведение матриц в несколько потоков. В отличие от предложенного в другом ответе варианта, распределяет вычисления между потоками более "справедливо". Поток не обязательно вычисляет строку новой матрицы целиком, вычисления могут начинаться и заканчиваться на любой ячейке матрицы.
import java.io.FileWriter; import java.io.IOException; import java.util.Random;
/** Поток-вычислитель группы ячеек матрицы. */ class MultiplierThread extends Thread { /** Первая (левая) матрица. */ private final int[][] firstMatrix; /** Вторая (правая) матрица. */ private final int[][] secondMatrix; /** Результирующая матрица. */ private final int[][] resultMatrix; /** Начальный индекс. */ private final int firstIndex; /** Конечный индекс. */ private final int lastIndex; /** Число членов суммы при вычислении значения ячейки. */ private final int sumLength;
/** * @param firstMatrix Первая (левая) матрица. * @param secondMatrix Вторая (правая) матрица. * @param resultMatrix Результирующая матрица. * @param firstIndex Начальный индекс (ячейка с этим индексом вычисляется). * @param lastIndex Конечный индекс (ячейка с этим индексом не вычисляется). */ public MultiplierThread(final int[][] firstMatrix, final int[][] secondMatrix, final int[][] resultMatrix, final int firstIndex, final int lastIndex) { this.firstMatrix = firstMatrix; this.secondMatrix = secondMatrix; this.resultMatrix = resultMatrix; this.firstIndex = firstIndex; this.lastIndex = lastIndex;
sumLength = secondMatrix.length; }
/**Вычисление значения в одной ячейке. * * @param row Номер строки ячейки. * @param col Номер столбца ячейки. */ private void calcValue(final int row, final int col) { int sum = 0; for (int i = 0; i < sumLength; ++i) sum += firstMatrix[row][i] * secondMatrix[i][col]; resultMatrix[row][col] = sum; }
/** Рабочая функция потока. */ @Override public void run() { System.out.println("Thread " + getName() + " started. Calculating cells from " + firstIndex + " to " + lastIndex + "...");
final int colCount = secondMatrix[0].length; // Число столбцов результирующей матрицы. for (int index = firstIndex; index < lastIndex; ++index) calcValue(index / colCount, index % colCount);
System.out.println("Thread " + getName() + " finished."); } }
class Main { /** Заполнение матрицы случайными числами. * * @param matrix Заполняемая матрица. */ private static void randomMatrix(final int[][] matrix) { final Random random = new Random(); // Генератор случайных чисел.
for (int row = 0; row < matrix.length; ++row) // Цикл по строкам матрицы. for (int col = 0; col < matrix[row].length; ++col) // Цикл по столбцам матрицы. matrix[row][col] = random.nextInt(100); // Случайное число от 0 до 100. }
//
/** Вывод матрицы в файл. * Производится выравнивание значений для лучшего восприятия. * * @param fileWriter Объект, представляющий собой файл для записи. * @param matrix Выводимая матрица. * @throws IOException */ private static void printMatrix(final FileWriter fileWriter, final int[][] matrix) throws IOException { boolean hasNegative = false; // Признак наличия в матрице отрицательных чисел. int maxValue = 0; // Максимальное по модулю число в матрице.
// Вычисляем максимальное по модулю число в матрице и проверяем на наличие отрицательных чисел. for (final int[] row : matrix) { // Цикл по строкам матрицы. for (final int element : row) { // Цикл по столбцам матрицы. int temp = element; if (element < 0) { hasNegative = true; temp = -temp; } if (temp > maxValue) maxValue = temp; } }
// Вычисление длины позиции под число. int len = Integer.toString(maxValue).length() + 1; // Одно знакоместо под разделитель (пробел). if (hasNegative) ++len; // Если есть отрицательные, добавляем знакоместо под минус.
// Построение строки формата. final String formatString = "%" + len + "d";
// Вывод элементов матрицы в файл. for (final int[] row : matrix) { // Цикл по строкам матрицы. for (final int element : row) // Цикл по столбцам матрицы. fileWriter.write(String.format(formatString, element));
fileWriter.write("
"); // Разделяем строки матрицы переводом строки. } }
/** * Вывод трёх матриц в файл. Файл будет перезаписан. * * @param fileName Имя файла для вывода. * @param firstMatrix Первая матрица. * @param secondMatrix Вторая матрица. * @param resultMatrix Результирующая матрица. */ private static void printAllMatrix(final String fileName, final int[][] firstMatrix, final int[][] secondMatrix, final int[][] resultMatrix) { try (final FileWriter fileWriter = new FileWriter(fileName, false)) { fileWriter.write("First matrix:
"); printMatrix(fileWriter, firstMatrix);
fileWriter.write("
Second matrix:
"); printMatrix(fileWriter, secondMatrix);
fileWriter.write("
Result matrix:
"); printMatrix(fileWriter, resultMatrix); } catch (IOException e) { e.printStackTrace(); } }
/** Однопоточное умножение матриц. * * @param firstMatrix Первая матрица. * @param secondMatrix Вторая матрица. * @return Результирующая матрица. */ private static int[][] multiplyMatrix(final int[][] firstMatrix, final int[][] secondMatrix) { final int rowCount = firstMatrix.length; // Число строк результирующей матрицы. final int colCount = secondMatrix[0].length; // Число столбцов результирующей матрицы. final int sumLength = secondMatrix.length; // Число членов суммы при вычислении значения ячейки. final int[][] result = new int[rowCount][colCount]; // Результирующая матрица.
for (int row = 0; row < rowCount; ++row) { // Цикл по строкам матрицы. for (int col = 0; col < colCount; ++col) { // Цикл по столбцам матрицы. int sum = 0; for (int i = 0; i < sumLength; ++i) sum += firstMatrix[row][i] * secondMatrix[i][col]; result[row][col] = sum; } }
return result; }
/** Многопоточное умножение матриц. * * @param firstMatrix Первая (левая) матрица. * @param secondMatrix Вторая (правая) матрица. * @param threadCount Число потоков. * @return Результирующая матрица. */ private static int[][] multiplyMatrixMT(final int[][] firstMatrix, final int[][] secondMatrix, int threadCount) { assert threadCount > 0;
final int rowCount = firstMatrix.length; // Число строк результирующей матрицы. final int colCount = secondMatrix[0].length; // Число столбцов результирующей матрицы. final int[][] result = new int[rowCount][colCount]; // Результирующая матрица.
final int cellsForThread = (rowCount * colCount) / threadCount; // Число вычисляемых ячеек на поток. int firstIndex = 0; // Индекс первой вычисляемой ячейки. final MultiplierThread[] multiplierThreads = new MultiplierThread[threadCount]; // Массив потоков.
// Создание и запуск потоков. for (int threadIndex = threadCount - 1; threadIndex >= 0; --threadIndex) { int lastIndex = firstIndex + cellsForThread; // Индекс последней вычисляемой ячейки. if (threadIndex == 0) { /* Один из потоков должен будет вычислить не только свой блок ячеек, но и остаток, если число ячеек не делится нацело на число потоков. */ lastIndex = rowCount * colCount; } multiplierThreads[threadIndex] = new MultiplierThread(firstMatrix, secondMatrix, result, firstIndex, lastIndex); multiplierThreads[threadIndex].start(); firstIndex = lastIndex; }
// Ожидание завершения потоков. try { for (final MultiplierThread multiplierThread : multiplierThreads) multiplierThread.join(); } catch (InterruptedException e) { e.printStackTrace(); }
return result; }
/** Число строк первой матрицы. */ final static int FIRST_MATRIX_ROWS = 1000; /** Число столбцов первой матрицы. */ final static int FIRST_MATRIX_COLS = 1000; /** Число строк второй матрицы (должно совпадать с числом столбцов первой матрицы). */ final static int SECOND_MATRIX_ROWS = FIRST_MATRIX_COLS; /** Число столбцов второй матрицы. */ final static int SECOND_MATRIX_COLS = 1000;
public static void main(String[] args) { final int[][] firstMatrix = new int[FIRST_MATRIX_ROWS][FIRST_MATRIX_COLS]; // Первая (левая) матрица. final int[][] secondMatrix = new int[SECOND_MATRIX_ROWS][SECOND_MATRIX_COLS]; // Вторая (правая) матрица.
randomMatrix(firstMatrix); randomMatrix(secondMatrix);
final int[][] resultMatrixMT = multiplyMatrixMT(firstMatrix, secondMatrix, Runtime.getRuntime().availableProcessors());
// Проверка многопоточных вычислений с помощью однопоточных. final int[][] resultMatrix = multiplyMatrix(firstMatrix, secondMatrix);
for (int row = 0; row < FIRST_MATRIX_ROWS; ++row) { for (int col = 0; col < SECOND_MATRIX_COLS; ++col) { if (resultMatrixMT[row][col] != resultMatrix[row][col]) { System.out.println("Error in multithreaded calculation!"); return; } } }
printAllMatrix("Matrix.txt", firstMatrix, secondMatrix, resultMatrixMT); } }
P.S. Среди особенностей - форматированный вывод матриц в файл и автоматическое определение размера матриц в функциях-вычислителях. В качестве бонуса - однопоточное вычисление и контроль многопоточного результата с помощью однопоточного.