Страницы

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

суббота, 1 февраля 2020 г.

Деплой бота на сервере Heroku

#python #python_3x #heroku


Может кто--нибудь дать инструкцию, как развернуть бота на сервере heroku (написанном
на python)? Спасибо заранее.
    


Ответы

Ответ 1



Первым делом создайте Git репозиторий в папке с ботом: git init Войдите в аккаунт Heroku: heroku login Создайте приложение: heroku create appname --region eu Создайте файл Procfile с содержимым: bot: python main.py Если бот на веб-хуках, замените bot на web. Но на бесплатном тарифе, бот будет засыпать каждые 30 минут если не будет подключений, по этому на Heroku free лучше держать ботов на лонг-поллинге. Но проблема с засыпанием веб приложения решается с помощью http://kaffeine.herokuapp.com/. Теперь нужно упаковать все зависимости проекта: pip freeze > requirements.txt Теперь наша папка выглядит приблизительно так: Procfile main.py requirements.txt Коммитим изменения: git add . затем git commit -m 'commit' Пушим на Heroku: git push heroku master Запускаем бота: heroku ps:scale bot=1 Смотрим логи: heroku logs -t На этом всё.

Ответ 2



В папке с проектом должны быть такие 3 файла: Proc web: python bot.py requirements.txt pyTelegramBotAPI==3.6.6 heroku==0.1.4 + другие модули (сгенерировать этот файл можно так: pip freeze > requirements.txt) runtime.txt python-3.7.0 или другая версия python Из папки, где находится проект, запускаете такие команды: git init git add . git commit -m "My first commit" heroku create git push heroku master Дополнительно рекомендую установить токен как переменную: heroku config:set TOKEN=7593654323:AAlkjHjhDZiWUD7Th4Dl_uPlkjpdorpoHGhgdsPVjQ (также можно установить переменные и на сайте Хероку) и обращаться к ней из программы import os os.environ['TOKEN'])

Получение числа из k-нотации: 1kkk -> 1000000000

#python #python_3x #python_36


Помогите пожалуйста создать простую функцию, в которую мы будем передавать 1 аргумент
а именно строку. Эта функция должна служить что бы пользователь мог сокращенно вводить
огромные числа к примеру (1k - 1000, 1.5kk - 1500000, 1kkk - 1000000000) мне маленький
набросок а дальше я сам попробую, спасибо
    


Ответы

Ответ 1



Пример: def k_to_number(num_str: str) -> int: i = num_str.index('k') num, size = num_str[:i], len(num_str[i:]) return int(float(num) * (1000 ** size)) print(k_to_number("1k")) # 1000 print(k_to_number("1.5kk")) # 1500000 print(k_to_number("1kkk")) # 1000000000 Ответ MaxU мне напомнил о похожем способе, с которым нужно быть очень осторожным: def k_to_number(num_str: str) -> int: return int(eval(num_str.replace('k', '*10**3'))) Дело в том, что eval (и его аналог exec) выполняют внутри себя питоничий код и в этом их опасность.

Ответ 2



Можно воспользоваться модулем numexpr: import numexpr as ne def to_num(s): s = (s.lower() .replace('k', '*10**3') .replace('m', '*10**6') .replace('g', '*10**9') .replace('t', '*10**12')) return ne.evaluate(s).item() Примеры: In [222]: print(to_num('1kKk')) 1000000000 In [223]: print(to_num('1m')) 1000000 In [224]: print(to_num('123.45m')) 123450000.0 In [225]: print(to_num('123.45m')) 123450000.0 In [226]: print(to_num('0.5k')) 500.0 In [227]: print(to_num('1K')) 1000

JAVA - как собирается .jar?

#java #jar


Подскажите "обывателю" пожалуйста какой мой ход действий.


Есть jar-файл
Если его открыть как архив, то в нем будут .class и .java файлы
.class скомпилированные
.java видимо исходники, так как они читаются 


Хочу поменять в исходнике часть функции. В этом понимание есть.
Как мне потом собрать обратно этот jar правильно? 
Нужно скомпилировать из .java обратно в .class и потом упаковать в jar.
Я могу просто скомпилированный .class добавить внутрь jar как в архив? Или нужно
еще как-то пересобирать весь jar?
Внутри jar есть еще манифест, но в нем ничего не прописано, только Manifest-Version: 1.0
    


Ответы

Ответ 1



Люди вы о чём? Вас спросили про jar файл, а вы сразу накидали кучу советов про maven, ItellijIDEA и пр. С чего вы решили, что у автора вопроса всё это есть? По сути. jar - это обычный ZIP-файл. Иногда бывает с подписями, контрольными суммами тогда что-то в нём исправить не получится. Если у вас простой файл, вы можете исправить java файл, перекомпилировать его с помощью javac в class файл и собрать jar файл заново с помощью обычного архиватора. В составе JDK есть файл JAR.EXE (если у вас Windows), который легко сделает это. Конечно удобнее всё делать в какой-либо Java IDE, если она у вас есть.

Ответ 2



Если используешь maven добавь в пом файле должно быть jar или соответствующий плагин. Читай мануал. javac MyApp.java jar -cf myJar.jar myApp

Как сделать изображение блоком?

#html #css #вёрстка


Как сделать данную картинку блоком и поместить внутри нее текст?
Затем, чтобы изображение меняло размер в зависимости от разрешения монитора?


    


Ответы

Ответ 1



.frame { background: url(https://i.stack.imgur.com/uDuvb.png) no-repeat; background-size: cover; width: 100%; position: relative; font-size: 3vw; } .frame:before { content: ''; display: block; padding-top: 171.5%; /* соотношение ширины/высоты картинки рамки */ } .frame-content { position: absolute; top: 0; left: 0; right: 0; bottom: 0; padding: 58% 20% 28%; }

Зимнее утро

Мороз и солнце; день чудесный!
Еще ты дремлешь, друг прелестный –
Пора, красавица, проснись;
Открой сомкнуты негой взоры
Навстречу северной Авроры,
Звездою севера явись!
Вечор, ты помнишь, вьюга злилась,
На мутном небе мгла носилась;

Луна, как бледное пятно,
Сквозь тучи мрачные желтела,
И ты печальная сидела –
А нынче... погляди в окно:

Под голубыми небесами
Великолепными коврами,
Блестя на солнце, снег лежит;
Прозрачный лес один чернеет,

...



Не знаю, как реализовать кодировку и декодировку QR-кодов в Python

#python #python_3x #qrcode


Хочу понять эту тему на простом примере:


Я ввожу текст и, соответсвенно, он преобразуется в QrCode. 
Загружая jpg(или любой другой формат) картинку с Qr-кодом, получаю зашифрованную
информацию.  




Полный текст ошибки:

    C:\Users\User>pip install git+https://github.com/ewino/qreader.git
Collecting git+https://github.com/ewino/qreader.git
  Cloning https://github.com/ewino/qreader.git to c:\users\user\appdata\local\te
mp\pip-req-build-oc3frfw6
  Error [WinError 2] Не удается найти указанный файл while executing command git
 clone -q https://github.com/ewino/qreader.git C:\Users\User\AppData\Local\Temp\
pip-req-build-oc3frfw6
Cannot find command 'git' - do you have 'git' installed and in your PATH?
You are using pip version 10.0.1, however version 18.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' comm
and.

    


Ответы

Ответ 1



Генерация QR-code. Используя qrcode: text = 'Hello World!' # pip install qrcode import qrcode img = qrcode.make(text) # In file img.save('qr_code_1.png') Результат: Чтение QR-code. Используя qreader: # pip install git+https://github.com/ewino/qreader.git import qreader # QR-код из пункта 1. url = 'https://i.stack.imgur.com/h4KD6.png' from urllib.request import urlopen data = qreader.read(urlopen(url)) print(data) # "Hello World!" Если нужно из файла, то передаем путь к нему или файловый объект: data = qreader.read('../qrcode__generate/qr_code_1.png') print(data) # Hello World! PS. Возможно, для qreader нужно будет reedsolo устанавливать (pip install reedsolo) PPS. Для выполнения pip install git+https://github.com/ewino/qreader.git инсталятор pip будет работать через git, поэтому нужно чтобы он стоял в системе

Как поделить пространство между блоками?

#html #css #css3


Нужно сделать блок из двух колонок. В левой написано "Описание", а в правой сам текст
описания.Не удается выставить ширину в 50% для "Описания". По факту отображается как
15-20%, т.е меньше чем необходимо. Правая колонка с текстом описания,наоборот, занимает
гораздо больше оставшихся 50%.

Описание

Пуховик из качественного материала. Материал синтетика,мех. Размер xl. Доступен также в других размерах


Ответы

Ответ 1



Нужно задать первому абзацу flex-shrink: 0, чтобы он не сжимался:

Описание

Пуховик из качественного материала. Материал синтетика,мех. Размер xl. Доступен также в других размерах

Или обоим абзацам задать width: 50%

Описание

Пуховик из качественного материала. Материал синтетика,мех. Размер xl. Доступен также в других размерах



Ответ 2



А если через column-count? Сам пока активно этим не пользуюсь, комментарии/критика приветствуются

Описание


Пуховик из качественного материала. Материал синтетика,мех. Размер xl. Доступен также в других размерах



Почему вызывается copy вместо move?

#cpp #ссылки #copy #move


Есть класс

class ArgClass {
public:
    ArgClass();
    ArgClass( const ArgClass& o );
    ArgClass& operator=( const ArgClass& o );
    ArgClass( ArgClass&& o );
    ArgClass& operator=( ArgClass&& o );
    ~ArgClass();
};


Шаблонная функция:

template< typename Type >
void wrapper( Type&& param )
{
    ArgClass tmp;
    tmp = param;
}


Почему данный код:

int main()
{
    ArgClass ac;
    wrapper( ArgClass() );
}


вызовет конструктор копирования в строке "tmp = param". Параметр функции wrapper
имеет тип ArgClass&&, и должен вызываться move конструктор копирования.
    


Ответы

Ответ 1



Потому что param внутри wrapper является локальной переменной, а значит, имеет имя, адрес... - словом, является lvalue. Чтобы он рассматривался при передаче в функцию rvalue как rvalue, нужно использовать прямую передачу (perfect forwarding) forward: tmp = std::forward(param);

Ответ 2



https://habr.com/post/226229/ В строке tmp = param вызовется оператор присваивания, почему конструктор копии? При явном вызове tmp = param; будет вызван оператор lvalue =, потому что он существует и определен, это гарантирует сохранность переданного объекта вне зависимости от того, как именно он принимается в функцию, как lvalue или rvalue. можно его удалить ArgClass& operator=( const ArgClass& o ) = delete; и убедиться, что компилятор пытается вызвать lvalue= class ArgClass { public: ArgClass() { std::cout << "base cons" << std::endl; }; ArgClass( const ArgClass& o ) { std::cout << "lv cons" << std::endl; }; ; ArgClass& operator=( const ArgClass& o ) { std::cout << "lv assign" << std::endl; return *this;};; ArgClass( ArgClass&& o ) { std::cout << "rv cons" << std::endl; };; ArgClass& operator=( ArgClass&& o ) { std::cout << "rv ass" << std::endl; return *this;};; ~ArgClass() { std::cout << "destr" << std::endl; };; }; template< typename Type > void wrapper( ArgClass&& param ) { ArgClass tmp; tmp = (param); } int main() { wrapper( ArgClass() ); system("pause"); } base cons base cons lv assign destr destr При явном вызове перемещения, будет вызван соответственно оператор rvalue= template< typename Type > void wrapper( ArgClass&& param ) { ArgClass tmp; tmp = std::move(param); } base cons base cons rv ass destr destr Для конструктора копии: template< typename Type > void wrapper( ArgClass&& param ) { ArgClass tmp(param); } base cons lv cons destr destr И перемещения: template< typename Type > void wrapper( ArgClass&& param ) { ArgClass tmp(std::move(param)); } base cons rv cons destr destr Такое поведение возможно обусловлено тем, что мув разрушает объект и именно явный вызов мув говорит о том, что объект будет утерян, в то время как обычные вызовы гарантируют сохранность объекта P.S. мувнуть объект можно и по обычной ссылке template< typename Type > void wrapper( ArgClass& param ) { ArgClass tmp(std::move(param)); } base cons rv cons destr destr

Ответ 3



Во-первых, о каком конструкторе вообще вы ведете речь, если у вас в коде вызывается оператор присваивания? Во-вторых, не вдаваясь в формальности: для именованного объекта никогда само по себе не будет выполняться move. param - это имя. Значит какой-то move исключено, пока вы явно не запросите его через std::move или std::forward. В данном контексте язык интересует не тот факт, что param имеет тип ArgClass&&, а тот факт, что выражение param является lvalue. Для lvalue будет вызван копирующий оператор присваивания, а не перемещающий.

Почему std::list<char>::iterator не выходит за начало

#cpp #алгоритм


std::string ss("some unknown word");
std::list word(ss.begin(), ss.end());
auto first = word.begin(), last = word.end(),
        middle = first;
size_t p = ss.size()/2;
std::advance(middle, p);   
while (last != first)
    *(--middle) = *(--last);  //результат:   own wordnown word


И почему этот цикл ведет себя как следующий? 

// while (p--)
//    *(--middle) = *(--last); //результат:    own wordnown word


Ведь, в принципе,  middle  должен был выходить за начало контейнера?!..

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

size_t p = ss.size()/4;
std::advance(middle, p);
while (last != first)
    *(--middle) = *(--last);  //результат:    word word unknown

    


Ответы

Ответ 1



Использование итератора end приведет к неопределенному поведению. Однако, список может быть построен таким образом, что сам список является узлом, и таким образом список оказывается закольцованным. Абстрактный пример: #include #include struct list_node_base //Базовый узел, который содержит два указателя на соседние узлы { list_node_base * next; list_node_base * prev; }; template struct list_node: list_node_base //Узел целевого типа добавляет данные к базовому узлу { list_node(T const & src): data(src) { } T data; }; template struct list: list_node_base //Список является узлом самого себя, но без данных { struct iterator { T & operator*() { return get_pointer()->data; } T * operator->() { return &get_pointer()->data; } bool operator!=(iterator const & rhv) { return p != rhv.p; } list_node * get_pointer() { return static_cast*>(p); } iterator & operator++() { p = p->next; return *this; } list_node_base * p; }; list(): list_node_base{this, this} {//Список в начальном состоянии состоит из одного узла - самого списка } void push(T const & v) { list_node_base * p = new list_node{T(v)}; prev->next = p;//this->next исправится автоматически при вставке первого элемента p->prev = prev; p->next = this;//Элемент следующий за последним - сам список prev = p; } iterator begin() { return iterator{next};//На первый узел указывает next } iterator end() { return iterator{this};//Сам список и является узлом end } }; int main() { list lst; lst.push("some"); lst.push("unknown"); lst.push("word"); auto current = lst.begin(); for(unsigned i = 0; i < 10; ++i) { if (current != lst.end()) {//Чтобы не разыменовать end std::cout << *current << std::endl;//ведь в нем нет члена data } ++current;//Для нашей реализации это валидно даже для end } } https://rextester.com/JBC22118 В данном списке все узлы, кроме одного, содержат член data. Этот "особенный" узел содержит нужные указатели на первый и последний элементы списка, и является основой итератора end. Так как в этом узле нет члена data, то get_pointer()->data в итераторе приведет к неопределенному поведению. Такие списки достаточно просты и удобны в реализации. Подобным способом реализован список в gcc: //g++ 5.4.0 #include #include #include int main() { std::list lst; lst.push_back("some"); lst.push_back("unknown"); lst.push_back("word"); auto current = lst.begin(); for(unsigned i = 0; i < 10; ++i) { if (current != lst.end()) { std::cout << *current << std::endl; } ++current; } } https://rextester.com/VMNO65384

Ответ 2



Итератор middle выйдет за пределы контейнера на 9 итерации, соответственно его разыменование приведёт к Неопределенному Поведению.

Преобразовать строки в числа в столбце DataFrame'а, избавившись от нецифровых символов

#python #строки #pandas #dataframe


Имеется датафрейм df_compliance:

name                                pass_info

Иванов Петр Александрович       4 520 802 159
Петров Михаил Иванович          4501256807
Сидоров Дим Димыч               4308 506310
Куприн Салтык Алекс             4513 № 056779
Воркутов Михаил Петрович        4501152999


Требуется привести колонку pass_info в одинаковый вид, чтобы получилось следующее:

 name                                pass_info

Иванов Петр Александрович       4520802159
Петров Михаил Иванович          4501256807
Сидоров Дим Димыч               4308506310
Куприн Салтык Алекс             4513056779
Воркутов Михаил Петрович        4501152999


Помогите разобраться как это сделать...

пытаюсь это сделать через df_compliance['pass_info'].apply(' ',join), но получается
ерунда :(
    


Ответы

Ответ 1



Воспользуйтесь Series.str.replace() и pd.to_numeric(): In [14]: df['pass_info'] = pd.to_numeric(df['pass_info'].str.replace('\D', ''), errors='coerce') In [15]: df Out[15]: name pass_info 0 Иванов Петр Александрович 4520802159 1 Петров Михаил Иванович 4501256807 2 Сидоров Дим Димыч 4308506310 3 Куприн Салтык Алекс 4513056779 4 Воркутов Михаил Петрович 4501152999 In [16]: df.dtypes Out[16]: name object pass_info int64 # <---- NOTE! dtype: object

Ответ 2



Вариант с регулярками: import re trim = re.compile("\D").sub('', s) df_compliance.pass_info.apply(trim)

Ответ 3



trim = lambda ss: ''.join(s for s in ss if s.isdigit()) df_compliance.pass_info.apply(trim)

Как осуществить слияние k сортированных списков

#python_3x #сортировка #list #память #время


Даны k отсортированных в порядке неубывания массивов натуральных чисел, каждое из
которых не превосходит 100. Требуется построить результат их слияния: отсортированный
в порядке неубывания массив, содержащий все элементы исходных k массивов.

Длина каждого массива не превосходит 10 ⋅ k.

Постарайтесь, чтобы решение работало за время k ⋅ log(k) ⋅ n, если считать, что входные
массивы имеют длину n.

Формат ввода

Первая строка входного файла содержит единственное число k, k ≤ 1024.

Каждая из следующих k строк описывает по одному массиву. Первое число каждой строки
равняется длине соответствующего массива, оставшиеся числа этой строки описывают значения
элементов этого же массива. Элементы массивов являются натуральными числами и не превосходят 100.

Формат вывода

Выходной файл должен содержать отсортированный в порядке неубывания массив, содержащий
все элементы исходных массивов.

Пример

Ввод

4
6 2 26 64 88 96 96
4 8 20 65 86
7 1 4 16 42 58 61 69
1 84

Вывод

1 2 4 8 16 20 26 42 58 61 64 65 69 84 86 88 96 96

Ограничение по времени выполнение скрипта 1 сек. для любого теста, ограничение по
используемой памяти: 10 МБ

Вот мой код:

import sys

int_str = ''
n = int(sys.stdin.readline().strip())
for i in range(int(n)):
    s = sys.stdin.readline().strip() + ' '
    count = int(s[:s.find(' ')])
    p, j = 0, 0
    for j in range(s.__len__()):
        if s[j] == ' ':
            p += 1
        if p == count+1:
            break
    int_str += s[s.find(' '):j]
    del (s,)

for i in sorted(int_str.lstrip().split(' '), key=lambda x: int(x) if x.isdigit() else 0):
    print(i, end=" ")


Ещё один вариант

import sys

n = int(sys.stdin.readline().strip())
int_list = []
for i in range(n):
    input = sys.stdin.readline().strip()
    data = list(map(int, input.split()))
    input = None
    n = data[0]
    a = data[1:n+1]
    int_list.extend(a)
    data = None

int_list.sort()

for li in int_list:
    sys.stdout.write(str(li) + ' ')
sys.stdout.write('\n')


Гномья сортировка

import sys

int_list = []
t = [0] * 101
n = int(sys.stdin.readline().strip())
for i in range(int(n)):
    s = sys.stdin.readline().strip()
    try:
        num = int(s[:s.find(' ')])
    except ValueError:
        continue
    for index, value in enumerate(s.split(' ')):
        if index == 0:
            continue
        elif index == num + 1:
            break
        try:
            t[int(value)] += 1
        except ValueError:
            pass
    del s

res = []
for i in range(101):
    res += [i] * t[i]

for r in res:
    print(r, end=' ')


Memory Limit и Time Limit близко
    


Ответы

Ответ 1



Так как в задаче есть ограничение на элементы массива: массивов натуральных чисел, каждое из которых не превосходит 100. то можно применить сортировку подсчётом, которая работает за линейное время. Но для C# возникает ещё одна проблема - это создание массива строк при считывании данных, которые на больших данных используют > 10Мб памяти. Я решила эту проблему с помощью запуска сборщика мусора. Моё решение: using System; using System.IO; namespace ConsoleApp { class Program { static void Main(string[] args) { short[] digitsCount = new short[101]; short k = Convert.ToInt16(Console.ReadLine()); string[] values; for (short i = 0; i < k; i++) { values = Console.ReadLine().Split(' '); for (short j = 1; j < values.Length; j++) { digitsCount[Convert.ToByte(values[j])]++; } GC.Collect(); } using (StreamWriter sw = new StreamWriter("output.txt")) { for (short i = 0; i < digitsCount.Length; i++) { for (short j = 0; j < digitsCount[i]; j++) { sw.Write(i + " "); } } } } } } Удачи на собеседовании!

Ответ 2



Сложность k * n Time Limit помогло убрать периодический вывод буфера, а не накопление его до N k = int(input()) count = {str(i): 0 for i in range(100)} total = 0 for list_index in range(k): a = input().split() size = int(a[0]) total += size if size > 0: for i in range(1, size + 1): count[a[i]] += 1 buff = [] for i in range(100): c = str(i) if i % 10 and buff: print(' '.join(buff), end=' ') buff = [] buff.extend([c] * count[c]) print(' '.join(buff)) Тест list + int() vs dict vs Counter from timeit import timeit from collections import Counter n = 10000000 str_list = [str(x) for x in range(n)] number = 10 print(timeit(""" for i in range(n): a[int(str_list[i]) % 100] += 1 """, setup='a = [0] * 100', number=number, globals=globals())) print(timeit(""" for i in range(n): d[str_list[i % 100]] += 1 """, setup='d = {str(i): 0 for i in range(100)}', number=number, globals=globals())) print(timeit(""" for i in range(n): d[str_list[i % 100]] += 1 """, setup='d = Counter(i for i in range(100))', number=number, globals=globals())) PyPy 3.5.3 (не понятно, почему Яндекс его не добавили): 6.919497203998617 1.7934346760011977 5.253608144004829 Python 3.7 27.728900675007026 17.81548438500613 25.83648096800607

Ответ 3



Тоже столкнулся с этой задачей. Начал с Python 3.6. Пробовал сортировку подсчетом и heapq.merge. Ни в какую не укладываюсь в 1 секунду на 20м тесте. Попробовал переписать на Go и сортировку подсчетом. Результат по времени абсолютно такой же как на Python. Видимо от языка не зависит. package main import ( "bufio" "fmt" "os" "strconv" "strings" ) func main() { const k = 100 reader := bufio.NewReader(os.Stdin) arraysNumString, _ := reader.ReadString('\n') arraysNumString = strings.TrimSuffix(arraysNumString, "\n") arraysNum, err := strconv.Atoi(arraysNumString) if err != nil { panic(err) } var counter [k]int for i := 0; i < arraysNum; i++ { inputString, _ := reader.ReadString('\n') inputString = strings.TrimSuffix(inputString, "\n") inputArray := strings.Split(inputString, " ") for idx, i := range inputArray { if idx == 0 { continue } j, err := strconv.Atoi(i) if err != nil { panic(err) } counter[j]++ } } for index, value:= range counter { for i := 0; i < value; i++ { fmt.Println(index) } } } Видимо нужно искать другой алгоритм или экономить на чтении строк.

Ответ 4



В задаче не оговорен запрет на использование стандартной библиотеки, поэтому моё решение выглядит следующим образом (для Python 3.4.3): from collections import Counter k = int(input()) a = Counter() for _ in range(k): a += Counter(map(int, input().split()[1:])) for key, c in sorted(a.items()): print("{} ".format(key) * c, end="") Ключевой момент здесь в том, что элементы в вводимых массивах не могут быть больше 100, а это значит, что количество ключей для Counter() не превысит это число. Даже в худшем случае, сортировка сотни целочисленных значений - простая задача. Опасения у меня вызывал только момент с суммированием Counter(), однако даже в последнем тесте, данный вариант затратил <5 mb памяти и уложился во время <0.7секунды.

Ответ 5



Реализация решения H. Case на основе встроенных типов. Результаты - 0.522s, 4.36Mb. n = int(input()) def counter_add(counter, value): if value in counter: counter[value] += 1 else: counter[value] = 1 counter = dict() for _ in range(n): ar = input().split() for i in ar[1:]: counter_add(counter, i) for i in range(101): i = str(i) if i in counter: print(' '.join([i] * counter[i]), end=' ')

Ответ 6



Я решила вот так - по-простому: k=int(input()) result={x:0 for x in range(0,101)} for i in range(k): current=input().split()[1:] for j in range(len(current)): cj = int(current[j]) result[cj] += 1 for key, v in result.items(): print("{} ".format(key) * v, end="")

Ответ 7



А я решил пойти путем использования одномерных векторов. Жаль, что Я не принял импорт NumPy... Пришлось тоже через сортировку подсчетом делать. Надеюсь, будет полезно и на такой вариант взглянуть. import sys import numpy as np k = sys.stdin.readline().strip() A = np.array([], dtype=np.uint8) for _ in range(int(k)): line = np.array(sys.stdin.readline().strip().split(" ")[1:], dtype=np.uint8) A = np.append(A, line) del line A = np.sort(A, kind="mergesort") A = A.tolist() print(*A)

Круговое передвижение по карте

#javascript #алгоритм #canvas


Есть очень большой двумерный массив - игровая карта. 
Есть маленький двумерный массив - текущая, видимая часть игровой карты.
Необходимо реализвать круговое (зацикленное) передвижение видимой части игровой карты.
Чтобы при досттижении конца Глобальной карты, начинало отображаться начало Глобальной
карты и так по кругу, в любую из сторон

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


Ответы

Ответ 1



Вам надо переписать зубодробительный код в функции getGlobalMapSector. Если я правильно понял, она выбирает из большого двумерного массива двумерный кусок с заворачиванием через границы большого массива. Все, что для этого нужно, - текущее положение левого-верхнего угла меньшего массива в большем и обращение к элементам большего массива с использованием остатка от деления. Вот одномерный случай: var sizeLarge = 10; var sizeSmall = 4; var start = 0; var large = []; for (var i = 0; i < sizeLarge; i++) { large.push(i + 1); } function getSmall() { if (start < 0) start += sizeLarge; var small = []; for (var j = 0; j < sizeSmall; j++) { small.push(large[(start + j) % sizeLarge]); } return small; } function showSmall() { console.log(JSON.stringify(getSmall())); } showSmall();

Ответ 2



Выборка видимой части карты происходит в функции getGlobalMapSector. Все остальное для визуализации const GlobalMap = []; const numSection = 30; //длина GlobalMap const viewNumSection = 11; //длина видимой части карты //центр видимой части карты const centerMap = { x: 10, y: 10, }; //видимая часть карта let currentMap = []; const isoCoords = { x: 0, y: 200, }; const tileWidth = 36; const canvas = document.getElementById("canvas"); const viewX = document.getElementById('rombX') const viewY = document.getElementById('rombY') const ctx = canvas.getContext("2d"); canvas.addEventListener("mousemove", mouseMoveOnMap); const colors = { 0: "green", 1: "blue", 2: "black", 3: "yellow", }; for (let i = 0; i < numSection; i++) { const row = []; GlobalMap.push(row); for (let h = 0; h < numSection; h++) { const obj = { x: i, y: h, type: Math.floor(Math.random() * 4), }; row.push(obj); } } currentMap = getGlobalMapSector(); drawMap(); function getGlobalMapSector() { let rangeArr = []; let length = GlobalMap.length; let rangeSize = viewNumSection; rangeSize = rangeSize % 2 !== 0 ? rangeSize : rangeSize + 1; //костыль let halfSize = Math.floor(rangeSize / 2); let minX = centerMap.x - halfSize; let minY = centerMap.y - halfSize; let startX = minX; let startY = minY; let endX = minX + rangeSize; let endY = minY + rangeSize; //передвижение внутри карты if ( minX >= 0 && minY >= 0 && minX + rangeSize <= length && minY + rangeSize <= length ) { // console.log("передвижение внутри карты") let endX = minX + rangeSize; let endY = minY + rangeSize; rangeArr = getSectorMapList(minX, endX, minY, endY, rangeArr); rangeArr = formResultMap(rangeArr, rangeSize); } //верхний левый угол карты else if (minX < 0 && minY < 0) { let startX = length - Math.abs(minX); let endX = length; let startY = length - Math.abs(minY); let endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = 0; endY = 0 + (rangeSize - (length - (length - Math.abs(minY)))); rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = 0; endX = 0 + (rangeSize - (length - (length - Math.abs(minX)))); rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = length - Math.abs(minY); endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); changeArr(rangeArr, length - Math.abs(minX), "x"); rangeArr = formResultMap(rangeArr, rangeSize); rangeArr = sortArr_Y(rangeArr, length - Math.abs(minY)); } //нижний правый угол карты else if (minX + rangeSize >= length && minY + rangeSize >= length) { let startX = minX; let endX = length; let startY = minY; let endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = 0; endX = minX + rangeSize - length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = 0; endY = minY + rangeSize - length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = minX; endX = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); changeArr(rangeArr, minX, "x"); rangeArr = formResultMap(rangeArr, rangeSize); rangeArr = sortArr_Y(rangeArr, minY); } //верхний правый угол карты else if (minX < 0 && minY + rangeSize > length) { let startX = length - Math.abs(minX); let endX = length; let startY = minY; let endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = 0; endX = 0 + (rangeSize - (length - (length - Math.abs(minX)))); rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = 0; endY = minY + rangeSize - length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = length - Math.abs(minX); endX = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); changeArr(rangeArr, length - Math.abs(minX), "x"); rangeArr = formResultMap(rangeArr, rangeSize); rangeArr = sortArr_Y(rangeArr, minY); } //нижний левый угол карты else if (minY < 0 && minX + rangeSize > length) { let startX = minX; let endX = length; let startY = length - Math.abs(minY); let endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = 0; endY = 0 + (rangeSize - (length - (length - Math.abs(minY)))); rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = 0; endX = minX + rangeSize - length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = length - Math.abs(minY); endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); changeArr(rangeArr, length - Math.abs(minX), "x"); rangeArr = formResultMap(rangeArr, rangeSize); rangeArr = sortArr_Y(rangeArr, minX); } //по центру верхней линии карты else if (minX < 0 && minY >= 0 && minY + rangeSize <= length) { let startX = length - Math.abs(minX); let endX = length; let startY = minY; let endY = minY + rangeSize; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = 0; endX = 0 + (rangeSize - (length - (length - Math.abs(minX)))); rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); changeArr(rangeArr, length - Math.abs(minX), "x"); rangeArr = formResultMap(rangeArr, rangeSize); rangeArr = sortArr_Y(rangeArr, minX); } //по центру нижней линии карты else if ( minY >= 0 && minY + rangeSize < length && minX >= 0 && minX + rangeSize > length ) { let startX = minX; let endX = length; let startY = minY; let endY = minY + rangeSize; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startX = 0; endX = minX + rangeSize - length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); changeArr(rangeArr, minX, "x"); rangeArr = formResultMap(rangeArr, rangeSize); } //по центру правой линии else if ( minX >= 0 && minX + rangeSize < length && minY >= 0 && minY + rangeSize > length ) { let startX = minX; let endX = minX + rangeSize; let startY = minY; let endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = 0; endY = minY + rangeSize - length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); rangeArr = formResultMap(rangeArr, rangeSize); rangeArr = sortArr_Y(rangeArr, minY); } //по центру левой линии else if (minY < 0 && minX >= 0 && minX + rangeSize <= length) { startX = minX; endX = minX + rangeSize; startY = length - Math.abs(minY); endY = length; rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); startY = 0; endY = 0 + (rangeSize - (length - (length - Math.abs(minY)))); rangeArr = getSectorMapList(startX, endX, startY, endY, rangeArr); sortArr_standart(rangeArr); rangeArr = formResultMap(rangeArr, rangeSize); rangeArr = sortArr_Y(rangeArr, length - Math.abs(minY)); } let center = rangeArr.length - 1 - halfSize; let centerSection = rangeArr[center][center]; centerMap.x = centerSection.x; centerMap.y = centerSection.y; return rangeArr; //сортирую элементы по Х и по У function sortArr_standart(arr) { arr.sort((a, b) => { let z = a.x - b.x; if (z == 0) { return a.y - b.y; } else { return z; } }); } //сортирую массив по У function sortArr_Y(arr, num) { for (let i = 0; i < arr.length; i++) { let g = arr[i]; changeArr(g, num, "y"); } return arr; } //перекидываю с конца массива в начало необходимые елементы //num - число, начиная с которого нужно переместить елементы function changeArr(arr, num, os) { let g = []; for (let i = 0; i < arr.length; i++) { let sector = arr[i]; if (sector[os] >= num) { g = arr.splice(i, arr.length); break; } } for (let h = g.length - 1; h >= 0; h--) { arr.unshift(g[h]); } } //делаю выборку из исходного двумерного массива function getSectorMapList(startX, endX, startY, endY, arr) { for (let x = startX; x < endX; x++) { for (let y = startY; y < endY; y++) { arr.push(GlobalMap[x][y]); } } return arr; } //формирую двумерный массив из исходного списка function formResultMap(arr, size) { let count = 0; let itogArr = []; for (let i = 0; i < size; i++) { let f = []; itogArr.push(f); for (let h = 0; h < size; h++) { itogArr[i][h] = arr[count]; count++; } } return itogArr; } } // меняет значение centerMap, currentMap function moveOnMap(way) { let step = 2; let nowX = centerMap.x; let nowY = centerMap.y; if (way == "top") { centerMap.x = nowX + step; if (nowX + step > GlobalMap.length - 1) { centerMap.x = nowX + step - GlobalMap.length; } } else if (way === "bottom") { centerMap.x = nowX - step; if (nowX - step < 0) { centerMap.x = GlobalMap.length - Math.abs(nowX - step); } } else if (way === "left") { centerMap.y = nowY - step; if (nowY - step < 0) { centerMap.y = GlobalMap.length - Math.abs(nowY - step); } } else if (way === "right") { centerMap.y = nowY + step; if (nowY + step > GlobalMap.length - 1) { centerMap.y = nowY + step - GlobalMap.length; } } currentMap = getGlobalMapSector(); drawMap(); } function drawMap() { let mapArr = currentMap; ctx.clearRect(0, 0, 400, 400); let tileHeight = tileWidth / 2; let halfHeight = tileHeight / 2; let startX = isoCoords.x; let startY = isoCoords.y; let startCenterX = startX + tileHeight; let startCenterY = startY; for (let i = 0; i < mapArr.length; i++) { for (let h = 0; h < mapArr[i].length; h++) { let centerX = startCenterX + 2 * halfHeight * (i + h); let centerY = startCenterY - halfHeight * (i - h); currentMap[i][h].centerX = centerX; currentMap[i][h].centerY = centerY; drawRectAroundCenter(centerX, centerY, mapArr[i][h].type); } } function drawRectAroundCenter(centerX, centerY, grid) { const step = 0; ctx.beginPath(); ctx.fillStyle = colors[grid]; ctx.strokeStyle = "black"; ctx.moveTo(centerX, centerY - halfHeight + step); ctx.lineTo(centerX + step - tileHeight, centerY); ctx.lineTo(centerX, centerY + halfHeight - step); ctx.lineTo(centerX + tileHeight - step, centerY); ctx.lineTo(centerX, centerY - halfHeight + step); ctx.stroke(); ctx.fill(); ctx.closePath(); } } const mouseCoords = { x: 0, y: 0, }; function getCursorPositionOnScene(event) { const clientX = event.clientX; const clientY = event.clientY; const position = canvas.getBoundingClientRect(); const mouseX = Math.floor(clientX - position.left); const mouseY = Math.floor(clientY - position.top); mouseCoords.x = mouseX; mouseCoords.y = mouseY; return; } function getTileCoordsOnMap() { const halfHeight = tileWidth / 2 / 2; const isoX = isoCoords.x; const isoY = isoCoords.y; const stepX = mouseCoords.x - isoX; const stepY = mouseCoords.y - isoY; const topX = 0.5 * stepX - stepY + isoX; const topY = 0.5 * stepY - stepX / 4 + isoY; const downX = 0.5 * stepX + stepY + isoX; const downY = 0.25 * stepX + 0.5 * stepY + isoY; let q = Math.pow(topX - isoX, 2) + Math.pow(topY - isoY, 2); const l = halfHeight * Math.sqrt(5); const lineTop = Math.sqrt(q); const rombX = Math.floor(lineTop / l); q = Math.pow(downX - isoX, 2) + Math.pow(downY - isoY, 2); const lineDown = Math.sqrt(q); const rombY = Math.floor(lineDown / l); return (coords = { x: rombX, y: rombY, }); } function mouseMoveOnMap(event) { getCursorPositionOnScene(event); if (!checkMouseCoordsOnMap()) return; const rombCoords = getTileCoordsOnMap(); const tile = currentMap[rombCoords.x][rombCoords.y] viewX.innerText = "X:" + tile.x; viewY.innerText = "Y:" + tile.y; } const borderIsoMap = { left: { x: 0, y: 0 }, top: { x: 0, y: 0 }, right: { x: 0, y: 0 }, bottom: { x: 0, y: 0 }, }; setBorderIsoMap(); function setBorderIsoMap() { const currentLength = currentMap.length; const height = tileWidth / 2; borderIsoMap.left.x = isoCoords.x; borderIsoMap.left.y = isoCoords.y; borderIsoMap.top.x = borderIsoMap.left.x + (tileWidth * currentLength) / 2; borderIsoMap.top.y = borderIsoMap.left.y - (height * currentLength) / 2; borderIsoMap.right.x = borderIsoMap.left.x + tileWidth * currentLength; borderIsoMap.right.y = borderIsoMap.left.y; borderIsoMap.bottom.x = borderIsoMap.top.x; borderIsoMap.bottom.y = borderIsoMap.left.y + (height * currentLength) / 2; } function checkMouseCoordsOnMap() { const coords = borderIsoMap; const left = coords.left; const top = coords.top; const right = coords.right; const bottom = coords.bottom; ctx.beginPath(); ctx.strokeStyle = "transparent"; ctx.moveTo(left.x, left.y); ctx.lineTo(top.x, top.y); ctx.lineTo(right.x, right.y); ctx.lineTo(bottom.x, bottom.y); ctx.stroke(); ctx.closePath(); return ctx.isPointInPath(mouseCoords.x, mouseCoords.y); } #scene { width: 400px; height: 400px; border: 1px solid; position: relative; } button { position: absolute; } .bottom { bottom: 70px; left: 80px; } .left { top: 80px; left: 90px; } .top { right: 80px; top: 80px; } .right { bottom: 70px; right: 60px; } #rombX { position: absolute; top: 10px; left: 10px; } #rombY { position: absolute; top: 30px; left: 10px; }
X: -1
Y: -1


Эффективный способ выбрать максимум

#sql #oracle #запрос #oracle12c


Как можно наиболее эффективно выбрать максимальное значение. Пока созрело 3 варианта:

1 - Классика

select max(log_id) from log where param = 16


2 - Извращения

select log_id from log where param = 16 order by log_id desc nulls last fetch next
1 rows only


3 - Аналитика

select v from
(
    select max(log_id) over () v from log where param = 16 
)
where rownum = 1


Судя по планам запросов в моей среде БД самый эффективный - последний. Может есть
варианты еще более эффективные?
    


Ответы

Ответ 1



А вы уверены, что это является узким местом в вашей БД? Или вы пытаетесь выполнить преждевременную оптимизацию до появления самой проблемы? Преждевременная оптимизация-корень всех бед Имхо, первый вариант с учетом того, что существует индекс по param должен отрабатывать моментально. На сколько я знаю, то индекс по полю по которому считается MAX тоже должен ускорить выборку, так как данные будут заранее отсортированы. +БД должна кешировать данные=> повторное выполнение запроса с другими параметрами должно отработать еще быстрее за счет того, что все данные были ранее вычитаны и загружены в ОЗУ. Если разница между этими 3 решениями и есть, то это какие-то считанные мс, которые не стоят уродства кода.

Ответ 2



Если у вас может быть более одной записи с param = 16, то 3-й вариант может вернуть неправильный результат, потому что предикат rownum = 1 отработает до max(log_id). Поэтому я бы выбрал 1-й вариант.

Как правильно составить html pattern

#javascript #html #jquery


В поле задаю тип string, и нужно чтобы проверялось на количество символов, максимально
7 штук, и чтобы можно было вводить только цифры в виде строки. Как это правильно реализовать,
подскажите пожалуйста:



$(function() {
  $("input[name=km]").on("invalid", function() {
    this.setCustomValidity("Код материала должен содержать 7 цифр.");
  });
});



Ответы

Ответ 1



pattern = [\d]{7} или pattern = [0-9]{7}

Ответ 2



Я бы совсем отказался от скрипта, если не предполагается более тщательная проверка и дополнительные действия: .input-wrap { position: relative; display: inline-block; } #km+span { position: absolute; top: 0; left: 0; width: 100%; border: 1px solid red; font: oblique .75em 'Arial'; text-align: center; color: #754; background-color: #fec; opacity: 0; pointer-events: none; transition: .5s ease; } #km:invalid+span { opacity: 1; top: 2.1em; }
Код материала должен содержать 7 цифр.


Протокол Диффи-Хеллмана не работает при некоторых значениях

#cpp #криптография


Почему при 


  p = 23, g = 5, a = 6, b = 15


ba равен ab, но при


  p = 23, g = 5, a = 116, b = 15


уже нет?

Какие типы, числа и диапазоны чисел должны быть для этого протокола?

#include  
#include  

int main() {
  unsigned long long int p = 23;
  unsigned long long int g = 5;
  unsigned long long int a = 6;
  unsigned long long int b = 15;
  unsigned long long int A = std::fmod(pow(g, a), p);
  unsigned long long int B = std::fmod(pow(g, b), p);
  unsigned long long int ba = std::fmod(pow(B, a), p);
  unsigned long long int ab = std::fmod(pow(A, b), p);
  return 1;
} 

    


Ответы

Ответ 1



Во-первых, в криптографических алгоритмах нужны точные целочисленные вычисления. Вы же используете приближенные вычисления с плавающей точкой. Ни о каком точном вычислении 5116 в вашем варианте речи идти не будет - это слишком большое число. Во-вторых, ваша последовательность действий описывает процесс формирования общего ключа после выбора секретных ключей a и b. В протоколе Диффи-Хеллмана секретные ключи a и b выбираются из мультипликативной группы по модулю p, то есть в вашем примере для p = 23 это должны быть значения в диапазоне [1, 22]. При чем здесь ваше 116, откуда вы его взяли и чего от него ожидали - не ясно. (Как правильно заметил @Zergatul в комментариях, при p = 23 протокол будет правильно работать и для a = 116. Но нет никакого смысла в том, чтобы выбирать число за пределами диапазона [1, 22]. В вашем случае это лишь привело к потере точности.)

Ответ 2



Никто так не считает остаток от деления после возведения в степень. Самая простая оптимизация выглядит так: int modpow(int a, int b, int m) // a^b % m { int result = 1; // 31 - для упрощения кода, на самом деле нужно брать длину числа в битах for (int i = 31; i >= 0; i--) { result = result * result % m; if (b & (1 << i)) result = result * a % m; } return result; } В реальных библиотеках для длинных чисел и криптографии дополнительно используют алгоритм Монтгомери.

Вертикальная центровка текста внутри <button>: каким образом это реализует user-agent?

#html #css


Вообщем, делал сегодня кнопочки и задумался: а как происходит центровка текста внутри
кнопок, ведь это inline-block элемент. Понятно, что изменив display или line-height,
отцентровать текстовое содержимое не сложно. Но вопрос в другом: как это делает user-agent?
Я обнулил line-height и padding, проверил все стили и не нашёл причину такого поведения.
Текст магическим образом центруется по вертикали внутри inline-block-элемента, или
я что-то пропустил?

PS: попробуйте это сделать внутри обычного div с display: inline block, padding:
0 и нулевым line-height у текста. 
    


Ответы

Ответ 1



Как насчет такого варианта? div { display: inline-block; height: 60px; background: #eee; padding: 0; margin: 0; } div:before { content: ""; display: inline-block; vertical-align: middle; height: 100%; }
Test
Если же вас волнует вопрос центровки текста по вертикали внутри UPD Если вытащить все свойства, которые превращают кнопку в кнопку, можно почти любой элемент стилизовать визуально: div { -apple-color-filter: none; -webkit-animation-trigger: auto; -webkit-appearance: button; -webkit-backdrop-filter: none; -webkit-backface-visibility: visible; -webkit-background-clip: border-box; -webkit-background-composite: source-over; -webkit-background-origin: padding-box; -webkit-background-size: auto; -webkit-border-fit: border; -webkit-border-horizontal-spacing: 0px; -webkit-border-image: none; -webkit-border-vertical-spacing: 0px; -webkit-box-align: stretch; -webkit-box-decoration-break: slice; -webkit-box-direction: normal; -webkit-box-flex: 0; -webkit-box-flex-group: 1; -webkit-box-lines: single; -webkit-box-ordinal-group: 1; -webkit-box-orient: horizontal; -webkit-box-pack: start; -webkit-box-reflect: none; -webkit-box-shadow: none; -webkit-clip-path: none; -webkit-column-axis: auto; -webkit-column-break-after: auto; -webkit-column-break-before: auto; -webkit-column-break-inside: auto; -webkit-column-progression: normal; -webkit-cursor-visibility: auto; -webkit-dashboard-region: ; -webkit-font-kerning: auto; -webkit-font-smoothing: auto; -webkit-hyphenate-character: auto; -webkit-hyphenate-limit-after: auto; -webkit-hyphenate-limit-before: auto; -webkit-hyphenate-limit-lines: no-limit; -webkit-hyphens: manual; -webkit-initial-letter: normal; -webkit-line-align: none; -webkit-line-box-contain: block inline replaced; -webkit-line-clamp: none; -webkit-line-grid: none; -webkit-line-snap: none; -webkit-locale: ru; -webkit-margin-after-collapse: collapse; -webkit-margin-before-collapse: collapse; -webkit-marquee-direction: auto; -webkit-marquee-increment: 6px; -webkit-marquee-repetition: infinite; -webkit-marquee-style: scroll; -webkit-mask-box-image: none; -webkit-mask-box-image-outset: 0px; -webkit-mask-box-image-repeat: stretch; -webkit-mask-box-image-slice: 0 fill; -webkit-mask-box-image-source: none; -webkit-mask-box-image-width: auto; -webkit-mask-clip: border-box; -webkit-mask-composite: source-over; -webkit-mask-image: none; -webkit-mask-origin: border-box; -webkit-mask-position: 0% 0%; -webkit-mask-repeat: repeat; -webkit-mask-size: auto; -webkit-mask-source-type: alpha; -webkit-nbsp-mode: normal; -webkit-print-color-adjust: economy; -webkit-rtl-ordering: logical; -webkit-svg-shadow: none; -webkit-text-combine: none; -webkit-text-decoration-color: rgba(0, 0, 0, 0.847059); -webkit-text-decoration-line: none; -webkit-text-decoration-skip: auto; -webkit-text-decoration-style: solid; -webkit-text-decorations-in-effect: none; -webkit-text-emphasis-color: rgba(0, 0, 0, 0.847059); -webkit-text-emphasis-position: over right; -webkit-text-emphasis-style: none; -webkit-text-fill-color: rgba(0, 0, 0, 0.847059); -webkit-text-orientation: mixed; -webkit-text-security: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-color: rgba(0, 0, 0, 0.847059); -webkit-text-stroke-width: 0px; -webkit-text-underline-position: auto; -webkit-text-zoom: normal; -webkit-transform-style: flat; -webkit-user-drag: auto; -webkit-user-modify: read-only; -webkit-user-select: text; align-content: normal; align-items: flex-start; align-self: auto; alignment-baseline: auto; alt: ""; animation-delay: 0s; animation-direction: normal; animation-duration: 0s; animation-fill-mode: none; animation-iteration-count: 1; animation-name: none; animation-play-state: running; animation-timing-function: ease; background-attachment: scroll; background-blend-mode: normal; background-clip: border-box; background-color: rgb(192, 192, 192); background-image: none; background-origin: padding-box; background-position: 0% 0%; background-repeat: repeat; background-size: auto; baseline-shift: baseline; border-bottom-color: rgba(0, 0, 0, 0.847059); border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; border-bottom-style: none; border-bottom-width: 0px; border-collapse: separate; border-image-outset: 0px; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(192, 192, 192); border-left-style: outset; border-left-width: 2px; border-right-color: rgb(192, 192, 192); border-right-style: outset; border-right-width: 2px; border-top-color: rgba(0, 0, 0, 0.847059); border-top-left-radius: 0px; border-top-right-radius: 0px; border-top-style: none; border-top-width: 0px; bottom: auto; box-shadow: none; box-sizing: border-box; buffered-rendering: auto; caption-side: top; caret-color: rgba(0, 0, 0, 0.847059); clear: none; clip: auto; clip-path: none; clip-rule: nonzero; color: rgba(0, 0, 0, 0.847059); color-interpolation: sRGB; color-interpolation-filters: linearRGB; color-rendering: auto; column-count: auto; column-fill: balance; column-gap: normal; column-rule-color: rgba(0, 0, 0, 0.847059); column-rule-style: none; column-rule-width: 0px; column-span: none; column-width: auto; content: ; counter-increment: none; counter-reset: none; cursor: default; cx: 0px; cy: 0px; direction: ltr; display: inline-block; dominant-baseline: auto; empty-cells: show; fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; filter: none; flex-basis: auto; flex-direction: row; flex-flow: row nowrap; flex-grow: 0; flex-shrink: 1; flex-wrap: nowrap; float: none; flood-color: rgb(0, 0, 0); flood-opacity: 1; font-family: system-ui; font-optical-sizing: auto; font-size: 11px; font-stretch: normal; font-style: normal; font-synthesis: style weight small-caps; font-variant: normal; font-variant-alternates: normal; font-variant-caps: normal; font-variant-east-asian: normal; font-variant-ligatures: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; font-weight: normal; fullscreen-auto-hide-duration: ; fullscreen-inset-bottom: ; fullscreen-inset-left: ; fullscreen-inset-right: ; fullscreen-inset-top: ; glyph-orientation-horizontal: 0deg; glyph-orientation-vertical: auto; grid-auto-columns: auto; grid-auto-flow: row; grid-auto-rows: auto; grid-column-end: auto; grid-column-start: auto; grid-row-end: auto; grid-row-start: auto; grid-template-areas: none; grid-template-columns: none; grid-template-rows: none; hanging-punctuation: none; height: 18px; image-rendering: auto; isolation: auto; justify-content: normal; justify-items: normal; justify-self: auto; kerning: 0; left: auto; letter-spacing: normal; lighting-color: rgb(255, 255, 255); line-break: auto; line-height: 13px; list-style-image: none; list-style-position: outside; list-style-type: disc; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; margin-top: 2px; marker-end: none; marker-mid: none; marker-start: none; mask: none; mask-type: luminance; max-height: none; max-width: none; min-height: 15px; min-width: 0px; mix-blend-mode: normal; object-fit: fill; object-position: 50% 50%; opacity: 1; order: 0; orphans: auto; outline-color: rgba(0, 0, 0, 0.847059); outline-offset: 0px; outline-style: none; outline-width: 0px; overflow-wrap: normal; overflow-x: visible; overflow-y: visible; padding-bottom: 3px; padding-left: 6px; padding-right: 6px; padding-top: 2px; page-break-after: auto; page-break-before: auto; page-break-inside: auto; paint-order: normal; perspective: none; perspective-origin: 19.9375px 30px; place-content: normal normal; place-items: flex-start normal; place-self: auto auto; pointer-events: auto; position: static; r: 0px; resize: none; right: auto; row-gap: normal; rx: 0px; ry: 0px; safe-area-inset-bottom: ; safe-area-inset-left: ; safe-area-inset-right: ; safe-area-inset-top: ; scroll-padding: 0px; scroll-padding-bottom: 0px; scroll-padding-left: 0px; scroll-padding-right: 0px; scroll-padding-top: 0px; scroll-snap-align: none none; scroll-snap-margin: 0px; scroll-snap-margin-bottom: 0px; scroll-snap-margin-left: 0px; scroll-snap-margin-right: 0px; scroll-snap-margin-top: 0px; scroll-snap-type: none; shape-image-threshold: 0; shape-margin: 0px; shape-outside: none; shape-rendering: auto; speak-as: normal; stop-color: rgb(0, 0, 0); stop-opacity: 1; stroke: none; stroke-color: rgba(0, 0, 0, 0); stroke-dasharray: none; stroke-dashoffset: 0px; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-width: 1px; tab-size: 8; table-layout: auto; text-align: center; text-anchor: start; text-decoration: none; text-indent: 0px; text-overflow: clip; text-rendering: auto; text-shadow: none; text-transform: none; top: auto; transform: none; transform-box: border-box; transform-origin: 19.9375px 30px; transform-style: flat; transition-delay: 0s; transition-duration: 0s; transition-property: all; transition-timing-function: ease; unicode-bidi: normal; vector-effect: none; vertical-align: baseline; visibility: visible; white-space: normal; widows: auto; width: 39.875px; will-change: auto; word-break: normal; word-spacing: 0px; word-wrap: normal; writing-mode: horizontal-tb; x: 0px; y: 0px; z-index: auto; zoom: 1; }
div
Но, магическое свойство, перемещающее текст по центру вы не найдете. Если ответить более точно на вопрос "Каким образом это реализует user-agent?", получится примерно следующее: "Написан код, который задает нужные параметры каждому тегу, в том числе и для

Бордер в процентах

#javascript #html #css #css3 #svg


Пытаюсь понять, как сделать такой бордер



Есть очевидный вариант с отрисовкой 100 картинок под каждый процент, но хотелось
бы что нибудь на css и js.
Примеров кода нет, т.к даже микроидей нет.
    


Ответы

Ответ 1



Проще, лучше и красивее - будет реализовать такое на SVG, например: var count = $(('#count')); $({ Counter: 0 }).animate({ Counter: count.text() }, { duration: 5000, easing: 'linear', step: function () { count.text(Math.ceil(this.Counter)+ "%"); } }); var s = Snap('#animated'); var progress = s.select('#progress'); progress.attr({strokeDasharray: '0, 251.2'}); Snap.animate(0,251.2, function( value ) { progress.attr({ 'stroke-dasharray':value+',251.2'}); }, 5000); body{text-align:center;font-family:sans-serif;} svg{width:30%;} 1% 50% 100% Источник: Круговой процентный прогресс бар | StackOverflow на русском Можно конечно и на JS\JQ, но будет это несколько кривовато и больше кода займёт.

конструирование контейнера из потока ввода

#cpp


Конструировать и инициализировать вектор можно различными способами. Например можно
создать вектор двумя итераторами другого контейнера:

std::list list{3, 5, 6, 7, 8};
std::vector v1,  v2(list.begin(), list.end());


можно также заполнить его  прямо из потока ввода:

std::copy(std::istream_iterator(std::cin), 
          std::istream_iterator(), std::back_inserter(v1));


Вопрос:  почему же  нельзя конструировать вектор из потока ввода, как с первым примером?
Например, если написать:

std::vector 
v3(std::istream_iterator(std::cin), std::istream_iterator());
for (int i : v3)
    std::cout << i <<' ';


то выдается ошибка:

/* error: no matching function for call to
 'begin(std::vector (&)(std::istream_iterator, std::istream_iterator
(*)()))'
      for (int i : v3)
                 ^*/

    


Ответы

Ответ 1



Дело не в конструировании и инициализации вектора. Ваше сообщение об ошибке говорит о том, что ваше объявление v3 было проинтерпретировано как объявление функции. Это [похоже на] баг (?) компилятора. Он неправильно (?) обработал most vexing parse. Замените хотя бы внешние () на {} в инициализации std::vector v3{ std::istream_iterator(std::cin), std::istream_iterator() }; Что интересно, таким "багом" страдают MSVC++ и Clang. Кто же тут прав? Эта тема здесь уже всплывала, но что-то я не могу ее найти. Также: Most vexing parse with a qualified-id - or not?

Ответ 2



Конструировать напрямую из istream_iterator можно, но судя по сообщению об ошибке, тут сработал most vexing parse. C точки зрения вашего компилятора, строка std::vector v3(std::istream_iterator(std::cin), std::istream_iterator()); выглядит одновременно как определение переменной v3 типа std::vector и объявление функции v3 с возвращаемым типом std::vector и двумя параметрами: типа std::istream_iterator с именем std::cin. Скобки вокруг имени игнорируются. Но :: в имени параметра - нонсенс. Насколько я понимаю, тут компилятор неправ - имя параметра не может содержать ::. GCC 8.2 компилирует эту строчку без ошибок, а Clang 7 ругается на ::. И то и другое явно более правильно. (Поведение GCC кажется мне более разумным, но я не знаю, что по этому поводу говорит стандарт.) типа std::istream_iterator (*)() (указатель на функцию без аргументов, возвращающую std::istream_iterator). В исходной строке звездочки не было, но параметры, являющиеся функциями, автоматически преобразуются в указатели на функции. (Подобно тому, как параметры-массивы преобразуются в указатели.) В таких случаях компилятор всегда истолковывает такие неоднозначные конструкции как объявления функций. Это и называется "most vexing parse", то есть "наиболее раздражающий парсинг" (потому что это часто застает программистов врасплох). Чтобы исправить ошибку, нужно изменить строчку так, чтобы она явно не выглядела как объявление функции. Например так: std::vector v3(std::istream_iterator(std::cin), std::istream_iterator{}); Или так: std::vector v3((std::istream_iterator(std::cin)), std::istream_iterator());

Как в Spring зарегистрировать объект-бин, созданный через new?

#java #spring


Можно ли привязать простой объект к контексту во время выполнения?
    


Ответы

Ответ 1



GenericApplicationContext.registerBean() спешит на помощь! // Любым способом получаем ApplicationContext. Самый простой способ - // за-autowire-ить его туда, откуда вы хотите зарегистрировать новый бин. GenericApplicationContext applicationContext = ... // Любым способом создаём объект, который хотим засунуть в контекст. Service service = new Service(); // Регистрируем его как бин. applicationContext.registerBean(Service.class, () -> service); // Не забываем обновить контекст. applicationContext.refresh(); // Теперь можно вытаскивать ваш объект из контекста! Service serviceFromContext = applicationContext.getBean(Service.class); Если в контексте уже есть AutowiredAnnotationBeanPostProcessor (а он, скорее всего, будет, если вы только не создавали контекст с нуля вручную), то у вашего бина даже будут работать свойства, помеченные аннотацией @Autowired. Если вам нужно зарегистрировать бин, который будет создан Spring-ом (например, вы хотите, чтобы Spring за-autowire-ил аргументы конструктора), вам нужно регистрировать BeanDefinition: public class Service { private RandomProvider randomProvider; @Autowired public Service(RandomProvider randomProvider) { this.randomProvider = randomProvider; } public int getNumber() { return randomProvider.getRandom().nextInt(); } } public class RandomProvider { public Random getRandom() { return new SecureRandom(); } } GenericApplicationContext applicationContext = ...; applicationContext.registerBean(RandomProvider.class, () -> randomProvider); BeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(Service.class).getBeanDefinition(); applicationContext.registerBeanDefinition("service", definition); applicationContext.refresh(); Service serviceFromContext = applicationContext.getBean(Service.class); System.out.println(serviceFromContext.getNumber()); Само собой, Spring сможет за-autowire-ить не только зарегистрированные вами бины, но и те, которые уже есть в контексте.

Ответ 2



@Configuration public class ApplicationConfig { @Bean public MyBean random() { return new MyBean(); } }

Ответ 3



Насколько я понял, то Вам нужно, чтобы бин создавался не один раз во время старта приложения, а каждый раз во время вызова бина. Для этого нужно указать Scope для бина, в вашем случае - это prototype @Bean @Scope("prototype") public Person getPerson() { return new Person(); } В таком случае, при каждом вызове будет создаваться новый экземпляр бина. Ссылки на данную тему: https://www.baeldung.com/spring-bean-scopes https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html

Плавная смена фона кнопки с градиентного на прозрачный

#css #css3 #html5 #css_animation


У меня есть кнопка с линейно-градиентным фоном, оранжевой рамкой и текстом.

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

Я также попытался перенести background, но это не работает, потому что у меня нет
конечной точки для transition, так как фон должен быть прозрачным. 



body {
    background-color: darkblue;
}

.button {
    background-image: linear-gradient(red,yellow);
    border: solid orange 2px;
    border-radius: 10px;
    color: white;
    padding: 15px 25px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 24px;
}




    


Ответы

Ответ 1



При использовании псевдоэлемента для фона, вы можете легко сделать это: body { background-color: darkblue; } .button { border: solid orange 2px; border-radius: 10px; color: white; padding: 15px 25px; text-align: center; text-decoration: none; display: inline-block; font-size: 24px; position: relative; overflow: hidden; z-index:0; background:transparent; } .button::before { content: ""; position: absolute; z-index:-1; top: 0; left: 0; right: 0; bottom: 0; background-image: linear-gradient(red, yellow); transition:1s; } .button:hover::before { opacity:0; } Вот еще одна идея без использования псевдоэлемента, где вы можете использовать изменение background-color и background-size. Хитрость заключается в том, чтобы сохранить один из цветов градиента прозрачным, чтобы мы могли видеть background-color (у вас может быть transition на прозрачный). Затем вы увеличиваете background-size, чтобы скрыть нижний цвет, и мы видим только прозрачный. body { background-color: darkblue; } .button { border: solid orange 2px; background-image: linear-gradient(transparent, yellow); background-size:100% 100%; background-color:red; border-radius: 10px; color: white; padding: 15px 25px; text-align: center; text-decoration: none; display: inline-block; font-size: 24px; transition:1s; } .button:hover { background-color:transparent; background-size:100% 500%; } Или подумайте о корректировке размера фона, чтобы иметь другой вид transition: body { background-color: darkblue; } .button { border: solid orange 2px; background: linear-gradient(red, yellow), transparent; background-size:100% 100%; background-position:left; /*change this to change the way the transtion happen*/ background-repeat:no-repeat; border-radius: 10px; color: white; padding: 15px 25px; text-align: center; text-decoration: none; display: inline-block; font-size: 24px; transition:1s; } .button:hover { background-size:0% 100%; }

Ответ 2



В данный момент это решение поддерживается только Хромом с включенными Experimental Web Platform features (а именно): CSS.registerProperty({ name: '--alpha', syntax: '', initialValue: 1, inherits: true, }) body { background-color: darkblue; } .button { --alpha: 1; background: linear-gradient(rgba(255,0,0,var(--alpha)), rgba(255,255,0,var(--alpha))) transparent; border: solid orange 2px; border-radius: 10px; color: white; padding: 15px 25px; text-align: center; text-decoration: none; display: inline-block; font-size: 24px; transition: --alpha 1s linear; } .button:hover { --alpha: 0; }

Что влияет на количество памяти занимаемой разными типами данных

#cpp #x64 #integer


Как я понимаю, обычно тип integer весит 4 байта, в том числе и unsigned integer. 
Но есть случаи где в зависимости от разрядности процессора integer может иметь как
2 байта так и 8. 
Не понимаю, как разрядность влияет на размер целочисленного типа и что это меняет
для разработчика кроме того, что в него можно вместить шире диапазон чисел(или меньший)?

UPD

Что значить переводить программу из x32 в x64? Грубо говоря, это использования типов
x64? Если я правильно понимаю, причина по которой программа написанная под x64 не будет
работать на x32, это оверхед по память в типах данных? 
Почему тогда мы можем допустим в Visual Studio выбрать под какую разрядность делать
build? Как это будет влиять на размер самой программы и размер, который будут забирать
обычные типы данных? 
    


Ответы

Ответ 1



Есть такая таблица соответствия размеров фундаментальных типов в зависимости от используемой модели данных: Модель данных в общем случае не привязана непосредственно к железу (разрядности процессора), и зависит от используемой операционной системы (если она присутствует). При этом должно быть очевидно, что на 32bit процессоре не удастся запустить 64bit ОС, но обратное вполне себе имеет место быть. Размер фундаментальных типов в конкретной реализации компилятора (т.е. под конкретную платформу) подбирается так, чтобы обеспечивать оптимальную производительность. Помимо увеличения диапазона значений фундаментальных типов, бОльшая разрядность позволяет адресовать больше памяти. Например, при 32bit можно адресовать не более 4Gb, а при 64bit уже 16Eb. Когда говорят о переводе программы с x32 на x64 имеют в виду, что должна обеспечиваться в первую очередь работоспособность программы в 64bit окружении. Т.е. что из-за изменения размеров типов ничего не сломается. Такого рода проблемы часто возникают, когда при первичной разработке закладываются на фиксированный размер фундаментальных типов, например, что указатель всегда будет 4 байта. А когда при сборке в 64bit режиме он "вдруг" становится в 2 раза больше программа просто начинает крашиться. Поэтому, чтобы программа была переносима между x32 ↔ x64 при необходимости обеспечить нужную разрядность вычислений стоит полагаться на типы из .

Ответ 2



Чтобы это понять, лучше написать пару программ на ассемблере, например простейший калькулятор. Основная причина разных размеров типа int, обычно кроется в количестве байт машинного слова архитектуры процессора (т.е. размер регистров), а также непосредственно в компиляторе. Обычно представление следующее: 8 бит int = 16 бит 16 бит int = 16 бит 32 бит int = 32 бита 64 бит int = 32 бита Необходимость 64 разрядных операционных систем и как следствие использования архитектур процессора возникла из-за роста памяти. Дело в том, что 32 разрядная ОС позволяет адресовать только 4 гигабайта оперативной памяти, т.к. 2^32 = 4294967296 байт. Регистры процессора архитектуры x86 AL, BL, CL, DL - 8 бит AX, BX, CX, DX - 16 бит EAX, EBX, ECX, EDX - 32 бит

Безопасно ли получать адрес члена невыровненной структуры

#cpp #c #выравнивание


Меня интересует следующий вопрос:

struct S
{
    // ...
    int i;
};

void f(uint8_t *_buf, size_t _offset)
{
    uint8_t *pu = _buf + _offset;
    S *ps = (S*)pu;
    int *pi = &(ps->i);// UB or not UB?

    int i;
    memcpy(&i, pi, sizeof(int));
}


У нас есть буфер байтов и смещение. По указанному смещению в буфере лежит объект
типа S. Этот объект имеет неверное выравнивание, как и поле i этого объекта.

Меня интересует, можно ли получить адрес поля i описанным образом, чтобы потом считать
int с указанного адреса безопасным способом - по одному байту или при помощи memcpy(). 
    


Ответы

Ответ 1



C99 6.3.2.3/7 A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. *Otherwise... Вольный перевод: Указатель на объект или неполный тип может быть преобразован в указатель на другой объект или неполный тип. Если результирующий указатель не выровнен корректно для типа, на который он будет указывать, поведение неопределено. Иначе... Т.е. со строгих слов стандарта Си получение любого не выровненного указателя, не зависимо от того, будет ли по нему доступ к памяти или нет — UB.

Ответ 2



Для этого будет достаточно взять смещение этого поля от начала структуры без каких-либо промежуточных указателей (подразумевается, что структура является standard layout type): ::std::memcpy(::std::addressof(i), _buf + _offset + offsetof(S, i), sizeof(i)); Что касается попытки преобразования указателя на объект с менее строгим выравниванием к указателю на объект с более строгим выравниванием, то в С++ поведение не специфицировано (то бишь задается реализацией): 8.5.1.10 Reinterpret cast [expr.reinterpret.cast] 7 An object pointer can be explicitly converted to an object pointer of a different type. 73 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T ”, the result is static_cast(static_cast(v)). [Note: Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. —end note ] 8.5.1.9 Static cast [expr.static.cast] 13 A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible (6.7.2) with a, the result is a pointer to b. Otherwise, the pointer value is unchanged by the conversion. Но вот использовать полученный указатель на структуру (даже если реализация правильно производит преобразование адреса) для получения указателя на поле этой структуры уже будет неопределенным поведением.

Как называется класс, у которого все поля (свойства) открытые

#c_sharp #net #классы #терминология


Яркий пример - модели в том же EntityFramework на .NET.

Точно помню, что где-то видел "научное" название таких классов, но как именно...

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

Не обёртка, не модель, не упаковка... на языке вертится.

public class Client
{
    public int Id{get;set;}
    public string Name{get;set;}
    ...
}

    


Ответы

Ответ 1



Это DTO: Data Transfer Object.

Как добавить растровое изображение в SVG и позиционировать на нем объекты?

#javascript #css #svg


Кто может подсказать вот какую штуку. На странице есть изображение, которое увеличивается
в зависимости от размера экрана. И на нем есть объекты 
Вопрос в том. как отпозиционировать эти объекты, чтобы они не слетали когда изображение
увеличивается?
Вот тут это реализовано(на последнем экране перед футером) https://straticainternational.com/products/broadway?variant=17254881820761
,но не могу докопаться как, потому что идет просчет через js как я понимаю.
Кто может подсказать как сделать?
    


Ответы

Ответ 1



Хочу добавить ещё один нюанс. Многие знают, что можно использовать tooltip SVG, который выводится при наведении курсора на объект. Чтобы это работало, нужно объект svg обернуть групповыми тегами и поместить внутрь теги <g> <title> Первая позиция установки раковины ..... Оказывается можно делать вложенные получая много строчные комментарии В примере ниже взят код @Stranger in the Q и добавлены много строчные tooltip body{ margin:0; overflow:hidden; } circle { fill:red; transition:200ms; cursor:pointer; stroke: transparent; } g:hover circle, g:hover path { transform: scale(1.2) rotate(45deg); } g:hover circle{ stroke-width: 0.5; stroke: white; } path { stroke: white; pointer-events: none; transition:200ms; } <svg viewbox="-100 -50 200 100" preserveAspectRatio="xMinYMin meet"> <image xlink:href="https://i.stack.imgur.com/fJW6o.png" x="-100" y="-100" height="200" width="200" /> <g transform="translate(-45,-2)"> <title> Первая позиция установки раковины <title>Крепление к каркасу Вторая позиция установки раковины <title>Крепление к каркасу Третья позиция установки раковины <title>Крепление к каркасу

Ответ 2



Вот вариант с использованием svg body{ margin:0; overflow:hidden; } circle { fill:red; transition:200ms; cursor:pointer; stroke: transparent; } g:hover circle, g:hover path { transform: scale(1.2) rotate(45deg); } g:hover circle{ stroke-width: 0.5; stroke: white; } path { stroke: white; pointer-events: none; transition:200ms; }

Можно ли сделать исполняемый файл приложения, написанного на java с расширением не jar, а exe?

#java #javafx #gui #jar #exe


Я создал приложение на языке java, но проблема в том, что после создания исполняемого
jar файла, я могу его запустить только со специальным программным обеспечением, соответственно
если кто-то попытается его запустить с другого компьютера, у него ничего не выйдет.
Как сделать исполняемый файл с расширением exe?
    


Ответы

Ответ 1



Для того, чтобы преобразовать jar в exe, нужно скачать Launch4j, установить путь к начальному файлу и конечному результату (с нужным расширением) Нажать на вкладку JRE, в пункте Min JRE version написать 1.6.0_22 После чего нажать на шестерёнку, вбить имя доп файла и нажать save

Ответ 2



Если вы используете IntelliJ тогда в Project Structure -> Artifacts -> выберите Native Bundle: All далее выберите во вкладке Build -> Build Artifact -> имя приложения -> Build *.exe файл вы найдете тут: USER\IdeaProjects\projectname\out\artifacts\projectname\bundles\projectname -> там будет находится ваш .exe файл.

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

#python #ооп #классы


У меня есть класс А и класс B, наследующий класс A. Кто подскажет функцию, выдающую
True или False на наследование классом B класса A?
    


Ответы

Ответ 1



Встроенные функции issubclass и isinstance отвечают на вопрос о наследовании: issubclass (class, classinfo) - является ли класс унаследованым (дочерним) от другого(их) класса(ов) isinstance (object, classinfo) - является ли объект сущностью класса(ов) class A: pass class B(A): pass issubclass (B, A) # True issubclass (A, B) # False isinstance (B(), A) # True Но, не путайте: isinstance (B, A) # False Класс B унаследован от A, но он не является его сущностью. Классы сами по себе объекты и функция isinstance к ним вполне применима. Класс B является сущностью класса type, который в свою очередь, унаследован от object, поэтому: isinstance (B, object) # True

Ответ 2



issublclass(B, A) Это точно функция, которую вы хотите. См. документацию для этой функции.

Поддерживают ли новые версии PHP HTTP методы нативно?

#php #http


Поддерживают ли новые версии PHP HTTP методы нативно?
    


Ответы

Ответ 1



PHP - это язык, HTTP - это протокол. Веб-сервер через FastCGI отдает то, что пришло из браузера, в PHP. PHP разбирает запрос (он в виде текста), инициализирует $_SERVER, $_GET, $_REQUEST и прочее. Какой метод был вызван - можно посмотреть через $_SERVER['REQUEST_METHOD']. Более PHP о HTTP методах не знает ничего. Более того, в запросе можно отправить вообще любое название в качестве HTTP метода. Также есть ответ на enSO

c# try catch Вложенные

#c_sharp


Как происходит обработка блока finally, если идет конструкция

try {
   try { }
   catch {}
   finally {}
}
catch {}
finally {}


Сработает тот и тот блок или же?
    


Ответы

Ответ 1



Должны отработать оба finally, т.к. блок finally Отрабатывает всегда (см. документацию), если исключение поймано. Если не поймано, то здесь уже нет гарантий выполнения.

Ответ 2



static void Main(string[] args) { try{ try{ throw new Exception(); } catch{ Console.WriteLine("Inner catch"); } finally{ Console.WriteLine("Inner finally"); } } catch{ Console.WriteLine("Outer catch"); } finally{ Console.WriteLine("Outer finally"); } } Результат: Inner catch Inner finally Outer finally

Поиск элемента в списке

#python #python_3x #list


Код:

users = [12390312, 12313123, 57289234, 21837129398]

userstats = 21837129398

print("Начинаю поиск")
for element in users:
    if userstats == users:
        break
    else:
        print("'userstats' нет в списке 'users'")

print("'userstats' есть в списке 'users'")


К примеру в коде у меня есть список c id пользователей

users = [12390312, 12313123, 57289234, 21837129398]


И есть сервер который отправляет мне по команде id пользователя в переменную userstats.

Предположим он отправил мне переменную с id 21837129398

В теории код должен найти в списке этот id, если находит, нужно чтобы выполнялся
этот код: print("'userstats' есть в списке 'users'")
А если не находит нужно чтобы выполнялся этот код: print("'userstats' нет в списке
'users'")

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


Ответы

Ответ 1



Для таких проверок можно воспользоваться оператором in. Если элемент есть в коллекции, то вернётся True, иначе - False. Код: users = [12390312, 12313123, 57289234, 21837129398] userstats = 21837129398 if userstats in users: print("'userstats' есть в списке 'users'") else: print("'userstats' нет в списке 'users'") stdout: 'userstats' есть в списке 'users' P. S.: Код можно сократить, используя аналог тернарного оператора: print("'userstats'", 'есть' if userstats in users else 'нет', "в списке 'users'")

Ответ 2



В случае бинарного ветвления можно воспользоваться индексированием при помощи булевого значения - False == 0 / True == 1: In [85]: verbs = ["нет", "есть"] In [86]: print(f"'userstats' {verbs[userstats in users]} в списке 'users'") 'userstats' есть в списке 'users'

Ответ 3



Как сделать это правильно с помощью in, вам уже написали. А вот почему не работает ваш код: for element in users: if userstats == users: break else: print("'userstats' нет в списке 'users'") Здесь у вас userstats - это один элемент. А users - это весь список. Очевидно, что условие userstats == users никогда не выполнится, т.к. один элемент не будет равен всему списку. Вам нужно было вместо userstats == users написать element == users, вот тогда бы ваш код заработал.

Объединение таблиц: Join(ы) или обычным способом?

#sql #postgresql


Читаю про Join(ы) и вижу такие примеры: 
Вот пример без Join(a)

SELECT prod_name, vend_name, prod_price, quantity FROM OrderItems, Products, Vendors
WHERE Products.vend_id = Vendors.vend_id
AND OrderItems.prod_id = Products.prod_id
AND order_num = 20007;


А вот пример с ним: 

SELECT vend_name, prod_name, prod_price 
FROM Vendors INNER JOIN Products
ON Vendors.vend_id = Products.vend_id;


Хотел спросить в чем отличие? Что первый что второй запрос выдают один и тот же результат.
Помню на лекциях говорили, что: Чем меньше кода тем лучше. В данном случае вижу что
с INNER JOIN кода меньше поэтому он лучше? Есть ли различия по производительности?
Почему все JOIN(ы) используют, а не первый пример допустим?
    


Ответы

Ответ 1



SQL - это декларативный язык. Вы просто говорите, что вы хотите получить, а СУБД уже сама решает, как ваши данные достать. Оба запроса описывают один и тот же результат. Помню на лекциях говорили, что: Чем меньше кода тем лучше. Это спорно. В моем окружении программисты придерживаются мнения, что код должен быть максимально понятным. Отсюда, краткость - не всегда хорошо. В данном случае вижу что с INNER JOIN кода меньше поэтому он лучше? Я склонен считать, что inner join лучше, т.к. с ним запрос более понятен. Это становится особенно актуально, когда в запросе таблиц 5 и больше. Есть ли различия по производительности? Часто движок СУБД изменяет запросы, по этому правильно сравнивать производительность запросов не по их тексту, а по плану запроса.

Ответ 2



from table1, table2 Это полный эквивалент для from table1 cross join table2 Из-за дополнительных условий в where может быть похож на inner join, но в первую очередь это декартово произведение множеств (Cartesian product). По стилю написания - это вопрос холивара и стандартов кодирования на проекте. Здесь не может быть однозначного ответа. В то же время синтаксис from table1, table2 - это только декартово произведение, тогда как синтаксис join даёт больше возможностей. Например, left join через декартово произведение не сделать. По производительности - планировщик СУБД в любом случае перепишет запрос так как ему больше понравится опираясь на свою статистику значений и модель cost-based оптимизатора. У postgresql вообще нет какого-то абстрактного оператора объединения таблиц. Потому что даже такую простую штуку как inner join для двух таблиц postgresql может выполнить минимум 6 разными способами: используя алгоритмы nested loops, hash или merge join и для прямого и для обратного порядка объединения таблиц. Затем помножить число возможных планов выполнения на возможности параллельного выполнения. Затем помножить на возможности выполнения по индексам (3 разных способа) или последовательным чтением всей таблицы. И на вопрос производительности запроса может ответить только конкретный explain (analyze,buffers)

Ответ 3



Оператор JOIN проще и понятнее, чем WHERE с кучей условий. Плюс JOIN, как правило, выполняется быстрее. Но, для того чтобы точно сказать о производительности нужно смотреть план выполнения конкретного запроса в конкретной СУБД.