Как сделать, чтобы баннер менялся на следующий каждые 5 секунд?
Компонент
Контроллер
public function list()
{
$banner = Banner::where('published', 1)->first();
return response()->json($banner);
}
Ответы
Ответ 1
Не нужно слать запросы для получения только одной сущности из БД.
Ниже пример постраничной зацикленной подгрузки контента: сама страница не перезагружается
в браузере, а происходит лишь подгрузка содержимого в компонент Vue через AJAX с параметром
page. При этом номер текущей "партии" содержимого page сохраняется в localStorage.
Применительно не только к баннерам: это может быть виджет новостей, ротатор изображений
и др.
Маршрутизатор
// BannerController замените на свой.
Route::get('/banners/list', 'BannerController@list');
Контроллер
public function list(Request $request)
{
// Обрабатываем запросы только по AJAX.
if ($request->ajax()) {
$banners = Banner::where('published', 1)->paginate(5);
return response()->json($banners, 200);
}
// Запретим прямой доступ на страницу.
abort(403, 'Unauthorized action.');
}
Примерное содержимое компонента:
#java #регулярные_выражения
Нужно чтобы строка типа "+ 5 7" делилась на знак, число, число. Знак любой, число
любое. Я пишу вот так:
String[] strArr = s.split(" ");
но этот код не срабатывает если между элементами несколько пробелов.
Ответы
Ответ 1
Попробуйте вот так:
String[] strArr = "+ 5 7".split("\\s+");
System.out.println(Arrays.toString(strArr));
\s - любой space character
+ - от одного до бесконечного кол-ва повторов
ну и в java нужно экранировать \ в регулярках, по этому \\
Неплохой ресурс для тестирования регулярок:
https://regex101.com/r/N1kUnk/1
#sql #oracle #oracle12c
Недавно проводили миграцию пользовательской системы на Oracle 12c и последнию версию
нашего продукта. Этот процесс заключался в запуске миграционных скриптов, которые в
основном добавляли и изменяли таблицы. Мы заметили, что при добавлении в таблицу новой
колонки со значением по умолчанию, появляется дополнительная скрытая колонка SYS_NC00002$.
Это можно воспроизвести так:
create table xxx (a integer);
alter table xxx add (b integer default 1);
select table_name, column_name, data_type, data_length, column_id,
default_length, data_default from user_tab_cols where table_name='XXX';
Table_Name|column_Name |data_Type|data_Length|column_Id|default_Length|data_Default|
------------------------------------------------------------------------------------
XXX |A |NUMBER | 22| 1| | |
XXX |SYS_NC00002$|RAW | 126| | | |
XXX |B |NUMBER | 22| 2| 1|1 |
Если посмотреть запросом значения этой скрытой колонки, то все они одинаковы:
select distinct SYS_NC00002$ from xxx;
Sys_Nc00002$|
-------------
01 |
Но что удивительно, если добавить сначало колонку и отдельным выражением определить
значение по умолчанию, то никакой скрытой колонки не появится:
create table xxy (a integer);
alter table xxy add (b integer);
alter table xxy modify b default 1;
select table_name, column_name, data_type, data_length, column_id,
default_length, data_default from user_tab_cols where table_name='XXY';
Table_Name|column_Name|data_Type|data_Length|column_Id|default_Length|data_Default|
-----------------------------------------------------------------------------------
XXY |A |NUMBER | 22| 1| | |
XXY |B |NUMBER | 22| 2| 1|1 |
Может кто-то объяснить, для чего эта скрытая колонка? И почему она появляется только
в первом примере, а во втором нет?
Ответы
Ответ 1
В релизе 11g была введена новая техника оптимизации для повышения производительности
DDL операций. Это нововведение позволяет экстремально снизить время выполнения, если
добавить NOT NULL колонку со значением по-умолчанию к существующей таблице. В релизе
12c эта техника оптимизации была расширена так же и для NULL колонок имеющих значение
по-умолчанию.
Посмотрим на примере таблицы с 1.000.000 строчек:
sql> create table xxy
as select rownum a from dual connect by level <= 1e6
;
Теперь добавим новую колонку и сравним 11g и 12c:
11g> alter table xxy add b number default 1;
--Table XXY altered. Elapsed: 00:01:00.998
12c> alter table xxy add b number default 1;
--Table XXY altered. Elapsed: 00:00:00.052
Обратите внимание на разницу во времени выполнения: 1M строчек изменены за 5 ms!
План выполнения показывает:
11g> select count(1) from xxy where b = 1;
COUNT(1)
----------
1000000
11g> select * from table(dbms_xplan.display_cursor);
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1040 (100)| |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | TABLE ACCESS FULL| XXY | 898K| 11M| 1040 (1)| 00:00:13 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("B"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
12c> select count(1) from xxy where b = 1;
12c> select * from table(dbms_xplan.display_cursor);
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 429 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| XXY | 1000K| 4882K| 429 (2)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00002$",0)),NULL,NVL("
B",1),'0',NVL("B",1),'1',"B")=1)
Note
-----
- statistics feedback used for this statement
План выполнения показывает для 12c в отличии от 11g довольно сложный предикат, который
использует новую скрытую колонку SYS_NC00006$. Этот предикат даёт понять, что БД внутри
себя считает, что колонка B потенциально может содержать значения отличающиеся от таковых
по-умолчанию. Из этого следует, БД в действительности не производит сразу изменение
всех строк, чтобы добавить значение по-умолчанию для новой колонки.
Для чего всё таки колонка SYS_NC00006$ создаётся?
12c> select column_name, virtual_column, hidden_column, user_generated
from user_tab_cols
where table_name = 'XXY'
;
COLUMN_NAME VIR HID USE
---------------- --- --- ---
B NO NO YES
SYS_NC00002$ NO YES NO
A NO NO YES
12c> select a, b, SYS_NC00002$ hid from xxy where a in (1,10);
A B HID
---------- ---------- ----------------
1 1
10 1
12c> update xxy set b=1 where a=10 and b=1;
1 row updated.
12c> select a, b, SYS_NC00002$ hid from xxy where a in (1,10);
A B HID
---------- ---------- ----------------
1 1
10 1 01
Обратите внимание на разницу в значениях колонки B и им соответствующих значениях
скрытой колонки SYS_NC00006$. БД просто проверяет на основании значения скрытой внутренней
колонки и с помощью функции SYS_OP_VECBIT, надо ли применять для колонки B значение
по-умолчанию, или колонка уже содержит реальное значение добавленное явным путём.
Почему скрытая колонка не создаётся в случае двух раздельных DDL выражений?
12c> alter table xxy add (b integer);
12c> alter table xxy modify b default 1;
12c> select count(b), count(coalesce(b,0)) nulls from xxy where b = 1 or b is null;
COUNT(B) NULLS
---------- ----------
0 1000000
В этом случае, значение новой колонки останется NULL для всех строчек. Так как никакого
обновления в действительности не требуется, то и в оптимизации нет никакой необходимости.
Статья на OTN, использованая как источник, была удалена или временно недостуна. В
настоящее время доступен только её перевод на китайский.
#python #python_3x
Делаю скрипт "Проверка на палиндром".Нужно чтоб скрипт проверял текст на наличие
спец.символов, а за тем убирал их если они были найдены.Вот собственно код:
text = input(" --> ")
array = ('.',',',' ','!')
for i in array:
if text.find(i):
text.replace(i,'')
if text.lower() == text[::-1].lower():
print('yes')
else:
print('no')
Программа работает,но скрипт не убирает спец.символы из текста,есть подозрения на
2 или 6 строки.Хелп ми!
Ответы
Ответ 1
text.replace(i,'') возвращает измененную строку, но сама переменная text остается
неизменной
но я бы делал это с использованием регулярных выражений:
import re
import string
def is_palindrome(s):
pat = f"[\s{re.escape(string.punctuation)}]"
s = re.sub(pat, "", s).lower()
return s == s[::-1]
тесты:
In [8]: is_palindrome("Assa")
Out[8]: True
In [9]: is_palindrome(".A-s,sa!")
Out[9]: True
In [10]: is_palindrome("Massa")
Out[10]: False
Ответ 2
Незнание синтаксиса губит,не обязательно проверять наличие запрещенных символов в
строке,можно сразу же их перебирать в цикле for и замещать методом text.replace().Если
символа в строке не окажется,ошибки не будет!Вот,собственно,код:
text = input(' --> ')
array = (',','.','!',' ')
for i in array:
text = text.replace(i,'')
if text.lower() == text[::-1].lower():
print('isPalindrom')
else:
print('isNotPalindrom')
#python #python_3x #словари
Есть следующий код:
dic = {'A':213, 'B':1424, 'F':412, 'Gs':asf}
for key in dic:
print(key)
Как можно проитерировать его, начиная со второго ключа?
Или, например, с ключа F?
Ответы
Ответ 1
В CPython реализации Python 3.6 элементы словаря сохраняют порядок данный им при
создании. Это деталь реализации, не гарантированная стандартом языка.
Начиная с Python 3.7 - это гарантированное поведение для любой реализации Python:
the insertion-order preservation nature of dict objects has been declared to be
an official part of the Python language spec.
Соответственно, для Python 3.7+ вы можете сделать:
In [6]: list(dic.keys())[2:]
Out[6]: ['F', 'Gs']
Для более ранних версий вы можете воспользоваться OrderedDict, как вам уже посоветовал
@Хачатур Саркисян:
In [9]: from collections import OrderedDict
In [10]: odic = OrderedDict(dic)
In [11]: list(odic.keys())[2:]
Out[11]: ['F', 'Gs']
Ответ 2
Словари в Python являются неупорядоченными структурами данных. Обращение по ключу
происходит за счет хэширования. Именно поэтому ваш вопрос не имеет под собой основания.
Чтобы реализовать нечто похожее используйте структуру данных OrderedDict.
Ответ 3
Как уже было сказано, ключи в словаре не имеют определенного порядка. Если нужно
пройтись по ключам в лексикографическом порядке, то такое решение:
Сортируем ключи, потом проходимся по ним. Пока не встретили ключ F - ничего не печатаем.
dic = {'A': 213, 'B': 1424, 'F': 412, 'Gs': 'asf'}
print_key = False
for key in sorted(dic):
if key == 'F':
print_key = True
if print_key:
print(key)
Вывод:
F
Gs
Ответ 4
num_of_row = 2
for i, x in enumerate(dic):
if i>=num_of_row:
print(i,x)
#python #python_3x
Как получить переменную name как глобальную?
import random
fruits = ('яблоко', 'абрикос', 'авокадо', 'банан', 'кокос', 'инжир')
def fruitName():
rand = random.randint(0,6)
name = fruits[rand]
print(name)
Понимаю, что вопрос достаточно глупой, но я только начала изучение программирования.
Ответы
Ответ 1
Для этого Вы можете воспользоваться инструкцией global, например:
global name
name = fruits[rand]
Возьмите на заметку!
Использовать глобальные переменные - ужасное архитектурное решение.
Если есть возможность избегать их - это обязательно нужно сделать.
Лучше сделать так:
import random
def get_rand_fruit(fruits: list) -> str:
rand_fruit = random.choice(fruits)
return rand_fruit
fruits = ('яблоко', 'абрикос', 'авокадо', 'банан', 'кокос', 'инжир')
name = get_rand_fruit(fruits)
print(name)
Ответ 2
В данном случае стоит воспользоваться готовой функцией random.choice() вместо написания
своей функции:
import random
fruits = ('яблоко', 'абрикос', 'авокадо', 'банан', 'кокос', 'инжир')
примеры:
In [105]: random.choice(fruits)
Out[105]: 'кокос'
In [106]: random.choice(fruits)
Out[106]: 'авокадо'
In [107]: random.choice(fruits)
Out[107]: 'инжир'
Ответ 3
Прислушайтесь к советам по поводу использования глобальных переменных
Обратите внимание на аргументы метода randint - обе границы инклюзивны.
import random
fruits = ('яблоко', 'абрикос', 'авокадо', 'банан', 'кокос', 'инжир')
def fruitName(fruits: list):
rand = random.randint(0,5) # <--- здесь
name = fruits[rand]
return name
print(fruitName(fruits))
#python #pandas #dataframe #numpy
Есть ДатаФрейм - таймсерия. Кое-какие значения в дата фрейме отсутствуют, а на их
месте стоит '.'
Я хочу заменить все значения с '.' на среднее апрфметическое двух соседних значений
колонки
Возможен так же вариант, что два или ти соседние значения принимают '.'. Т. е. для
исчисления показателей надо брать не соседние, а соседние значения, которые не ровняются '.'
Подскажите пжл как это сделать
Пример входных данных:
DJIA
3
.
5
6
Пример выходных данных:
DJIA
3
4
5
6
где 4 = (3+5)/2
Пробую вот так:
for i in data['DJIA']:
if i == '.':
data['DJIA'][i] = (data['DJIA'][i-1] + data['DJIA'][i+1])/2
Здесь ошибка очевидна:
TypeError Traceback (most recent call last)
in
1 for i in data['DJIA']:
2 if i == '.':
----> 3 data['DJIA'][i] = (data['DJIA'][i-1] + data['DJIA'][i+1])/2
TypeError: unsupported operand type(s) for -: 'str' and 'int'
Как правильно реализовать этот функционал?
Ответы
Ответ 1
Воспользуйтесь методом Series.interpolate():
data = pd.read_csv(r"D:\download\DJIA.csv", na_values=["."], parse_dates=["DATE"])
data["DJIA"] = data["DJIA"].interpolate()
Пример для данных из вашего предыдущего вопроса:
In [18]: data.loc[110:130]
Out[18]:
DATE DJIA
110 2009-12-24 10520.10
111 2009-12-25 NaN
112 2009-12-28 10547.08
113 2009-12-29 10545.41
114 2009-12-30 10548.51
115 2009-12-31 10428.05
116 2010-01-01 NaN
117 2010-01-04 10583.96
118 2010-01-05 10572.02
119 2010-01-06 10573.68
120 2010-01-07 10606.86
121 2010-01-08 10618.19
122 2010-01-11 10663.99
123 2010-01-12 10627.26
124 2010-01-13 10680.77
125 2010-01-14 10710.55
126 2010-01-15 10609.65
127 2010-01-18 NaN
128 2010-01-19 10725.43
129 2010-01-20 10603.15
130 2010-01-21 10389.88
In [19]: data["DJIA"] = data["DJIA"].interpolate()
In [20]: data.loc[110:130]
Out[20]:
DATE DJIA
110 2009-12-24 10520.100
111 2009-12-25 10533.590
112 2009-12-28 10547.080
113 2009-12-29 10545.410
114 2009-12-30 10548.510
115 2009-12-31 10428.050
116 2010-01-01 10506.005
117 2010-01-04 10583.960
118 2010-01-05 10572.020
119 2010-01-06 10573.680
120 2010-01-07 10606.860
121 2010-01-08 10618.190
122 2010-01-11 10663.990
123 2010-01-12 10627.260
124 2010-01-13 10680.770
125 2010-01-14 10710.550
126 2010-01-15 10609.650
127 2010-01-18 10667.540
128 2010-01-19 10725.430
129 2010-01-20 10603.150
130 2010-01-21 10389.880
Ответ 2
Если хочется сделать так просто, как то, что приводит к ошибке, то надо немного усложнить
другую часть кода
for i in range(len(data['DJIA'])):
if data['DJIA'][i] == '.':
data['DJIA'][i] = (data['DJIA'][i-1] + data['DJIA'][i+1])/2
#c_sharp #wpf
я использую dictionary в C# для быстрой проверки существования элемента в массиве
по ключу, по факту значение ключа мне не нужно, выглядит это так:
public void update_object_select_contour(MyObject myObject)
{
List list_position_tmp = myObject.list_position;
Dictionary dictionary_position_tmp = new Dictionary();
for (int i = 0; i < list_position_tmp.Count; i++)
{
dictionary_position_tmp.Add(list_position_tmp[i].ToString(), 0);
}
if(dictionary_position.ContainsKey(new Vector2i(5, 5).ToString()))
{
//Поиск элемента по ключу
}
}
То есть я закидываю координаты точек в dictionary и потом проверяю есть ли они там
по нужному мне поиску и у меня есть 2 вопроса:
1) Какую структуру хранения данных можно использовать для этого?(пытался найти деревья
в C#, так и не нашел) Хотелось бы чтобы выглядело это примерно так:
Dictionary
2) Какой лучше использовать ключ для хранения положений координат? Как я знаю преобразовывать
пары к тексту и хранить как текст не лучшая идея
Ответы
Ответ 1
Вы используете словарь. Словарь - это когда у вас есть ключ и есть значение, ассоциированное
с ключом.
То, что вам нужно, называется HashSet.
Если вы хотите хранить в HashSet координаты, то тогда координаты желательно должны
быть целыми числами, так как дробные числа могут быть не равны даже если они были посчитаны
по одной и той же формуле просто из за наличия погрешности.
Но вот с целыми числами проще. Но тут нужно иметь ввиду, так как, если вы будете
хранить координаты в HashSet, который использует хеш функцию для хранения и хеш
функцию и функцию эквивалентности для поиска элементов, вас в классе координат надо
перегрузить методы Equals и GetHashCode. Вот пример:
public class Coordinates2D
{
public int X { get; }
public int Y { get; }
public Coordinates2D(int x, int y)
{
X = x;
Y = y;
}
protected bool Equals(Coordinates2D other)
{
return X == other.X && Y == other.Y;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Coordinates2D) obj);
}
public override int GetHashCode()
{
unchecked
{
return (X * 397) ^ Y;
}
}
}
Теперь этот класс можно использовать в HashSet
var set = new HashSet();
set.Add(new Coordinates2D(10, 25));
Console.WriteLine(set.Contains(new Coordinates2D(1, 1))); // false
Console.WriteLine(set.Contains(new Coordinates2D(10, 25))); // true
Вывод очевиден
#java #android #kotlin #emoji
Условия: Есть приложение, содержащее EditText.
Задача: Сделать EditText, который позволяет вписать в себя только один любой Emoji
icon или какой-нибудь один символ.
Идеи: Я пробовал прописать в параметрах EditText android:maxLength="1", но в таком
случае некоторые emoji просто не пишутся. Предполагаю, это происходит потому, что некоторые
emoji состоят из нескольких других emoji, которые в последствии объединяются, то есть
они имеют длину больше одного символа.
Вопрос: Как осуществить задуманное?
Ответы
Ответ 1
Используйте Emoji Compatibility support library.
Ответ 2
Удалось реализовать без дополнительных библиотек:
Создаём Boolean переменную editTextFlag, которая используется для того, чтобы пресекать
бесконечные изменения текста в EditText, вызванные в результате команд MyEditText.setText(...).
(Дальше станет понятнее зачем нужна эта переменная.)
Ставим на EditText улавливатель изменений текста (ввода или удаления) командой .addTextChangedListener(...).
В нём по дефолту находится три функции: afterTextChanged, beforeTextChanged и onTextChanged.
Нам понадобится только одна: "beforeTextChanged", которая вызывается за момент до того,
как введётся текст.
s - в данной функции это текст, который был в EditText до изменения
after - количество символов в EditText после изменения
В "beforeTextChanged" я создал три условия:
(editTextFlag && after == 0) - вызывается когда пользователь удаляет символ или emoji,
то есть количество символов в EditText после изменения равно 0
(editTextFlag && HabitIconEditText.text.isNotEmpty()) - вызывается, когда в EditText
уже есть какой-то символ или emoji icon и пользователь пытается добавить ещё один.
Мы ему это не позволяем и пишем в EditText текст, который был до изменения, то есть
текст s, командой MyEditText.setText(s). Ну и для красоты перемещаем курсор EditText
в конец строки командой MyEditText.setSelection(s.length).
Ну else вызывается когда не подходит ни одно из вышеперечисленных условий. В данном
случае оно просто переключает переменную editTextFlag обратно на true. Дело в том,
что при вызове команды .setText( ... ) addTextChangedListener вызывается второй раз.
Так как при первом вызове editTextFlag переключилось на false, то нужно вернуть эту
переменную обратно на на true, делается это как раз при втором вызове, в этом условии else.
Вот собсна сам код:
var editTextFlag = true
MyEditText.addTextChangedListener(object : TextWatcher
{
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int)
{
when
{
(editTextFlag && after == 0) -> {
editTextFlag = false
MyEditText.setText("")
}
(editTextFlag && HabitIconEditText.text.isNotEmpty()) -> {
editTextFlag = false
MyEditText.setText(s)
MyEditText.setSelection(s.length)
}
else -> {
editTextFlag = true
}
}
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count:
Int) {}
override fun afterTextChanged(s: Editable) {}
})
#python #наследование #методы
Разбираюсь сейчас с наследованием в Python, а также с магическими методами. Имеется код:
class Researcher:
def __getattr__(self, name):
return 'Nothing found :()\n'
def __getattribute__(self, name):
print('Looking for {}'.format(name))
return super().__getattribute__(name)
obj = Researcher()
print(obj.attr)
print(obj.method)
print(obj.DFG2H3J00KLL)
Возник вопрос: откуда объект object() (который создался после вызова super()) знает
о методе __getattr__ класса Researcher? Разве базовый класс знает что-то про методы
потомков?
Ответы
Ответ 1
super() вовсе не возвращает просто объект родительского класса.
В этом легко убедиться, если перед строчкой где вы его вызываете поставить print(super()).
Если такое проделать, то код в этом месте выведет:
, >
Как видите, это не экземпляр родительского класса object. Это особый объект-обёртка,
который управляет вызовом методов из классов выше по иерархии для текущего объекта.
И вот эта обёртка и знает всё и про методы Researcher, и про всех его родителей.
UPD: Действительно, как правильно отметил автор вопроса в комментариях, если заменить
super() на object(), то код всё равно работает. Но это уже не связано с наследованием,
а связано с нюансами работы __getattr__ и __getattribute__
Дело в том, что __getattribute__, если он реализован, то он срабатывает для вообще
всех обращений к атрибутам - как к существующим, так и к несуществующим. В то время,
как __getattr__ срабатывает только для обращения к несуществующим атрибутам - то есть
тогда, когда при обращении к атрибуту произошло исключение AttributeError.
То есть вот что происходит, когда вы меняете super на object:
Код делает обращение к атрибуту объекта.
Так как это объект класса Researcher, для которого есть метод __getattribute__, то
код выполняет именно этот метод.
Внутри него идёт обращение к object().__getattribute__(name)
Для экземпляра класса object обращение к аттрибуту работает стандартно, то есть для
неизвестного аттрибута, такого как DFG2H3J00KLL будет выброшено исключение AttributeError
Т.к. при возникновении этого исключение всегда проверяется, есть ли у объекта __getattr__,
и так как всё это происходит всё ещё для экземпляра Researcher, а у него этот метод
есть, то именно он и срабатывает.
Проиллюстрировать это можно следующими примерами.
Демонстрация того, что исключение AttributeError действительно выбрасывается:
class Researcher:
def __getattr__(self, name):
return 'Nothing found :()\n'
def __getattribute__(self, name):
print('Looking for {}'.format(name))
try:
object().__getattribute__(name)
except Exception as e:
print('!!! ', type(e))
obj = Researcher()
print(obj.attr)
print(obj.method)
print(obj.DFG2H3J00KLL)
Демонстрация того, что даже если мы не будем обращаться ни к object, ни к super,
а просто руками выбросим AttributeError, то всё будет работать так же, как и изначально:
class Researcher:
def __getattr__(self, name):
return 'Nothing found :()\n'
def __getattribute__(self, name):
print('Looking for {}'.format(name))
raise AttributeError
obj = Researcher()
print(obj.attr)
print(obj.method)
print(obj.DFG2H3J00KLL)
#javascript #html #css #jquery
Как сделать подобие подсветки синтаксиса?
На входе есть строка 1235aa2323aa
1235aa2323aa
На выходе должно получится что-то вроде 1235aa2323aa, где цифры и буквы имеют разные
css стили которые применяются при вводе символов.
Ответы
Ответ 1
Такой костыль придумался... поставить поверх вашего элемента прозрачный textarea
(input), ровно с теми же размерами и шрифтом, а при вводе текста - обновлять его в
span. Проблема в том, что caret-color плохо поддерживается браузерами.
let inp = document.querySelector('.input_text');
let invis = document.querySelector('.invis');
inp.innerHTML = color(inp.innerText);
invis.addEventListener('input', function() {
inp.innerHTML = color(this.value);
this.style.height = (this.scrollHeight + 2) + 'px';
});
function color(txt) {
return txt.replace(/(\d+)/g, '$1')
}
.input_text {
display: inline-block;
width: 200px;
background-color: #22282b;
padding: 5px;
box-sizing: border-box;
color: #f7ed7e;
font-size: 18px;
font-family: 'Helvetica';
}
.number {
color: #ed593c;
}
.invis {
position: absolute;
left: 0;
width: 200px;
padding: 4px;
font-size: 18px;
font-family: 'Helvetica';
box-sizing: border-box;
background-color: transparent;
color: transparent;
caret-color: #f7ed7e;
outline: none;
border: 1px solid red;
resize: none;
overflow: hidden;
}
1235aa2323aa
Ответ 2
Через replace искать что подсветить и делать обертку с нужными стилями https://jsfiddle.net/1jm2cfqz/
document.querySelector('.input_text').innerHTML = document.querySelector('.input_text').innerHTML.replace(/\d/g,
'$&')
Ответ 3
Обернул каждый символ в тэг
$(document).ready(function() {
$(".my-text").keydown(function(event) {
const parElem = $(".my-text")
event.preventDefault();
let newEl;
const kCode = event.keyCode;
if (kCode >= 48 && kCode <= 57) {
newEl = `${String.fromCharCode(kCode)}`;
} else {
newEl =`${String.fromCharCode(kCode)}`;
}
if(kCode === 8) {
$('span').last().remove();
} else {
parElem.html(parElem.html() + newEl)
}
});
});
.num {
color: red;
}
.str {
color: blue;
}
text
Нужно доработать поведение для других keyCode-ов, но вроде-бы работает
#python
В каком виде в оперативной памяти храниться генератор при итерации по нему?
Например:
res = (num for num in range(10**100000)
for el in res:
print(el)
Понятно, что сам генератор храниться как объект в оперативной памяти и занимает некоторое
определенное место. Но что происходит при непосредственной итерации по нему? Какую
память начинает занимать сам генератор res после 1-ой, 2-ой и так далее итераций?
Ответы
Ответ 1
res = (num for num in range(10**100000)
приблизительно соответствует следующему коду
def f():
for num in range(10**100000)
yield num
res = f()
Здесь f – это сопрограмма, специальная функция, которая приостанавливает выполнение
после каждого yield, давая возможность вызывающей стороне забрать сгенерированное значение,
а также передать какое-нибудь значение внутрь функции.
Сопрограмма возобновит выполнение с того места, где остановилась, когда вызывающая
сторона попросит следующее значение. Если значений не осталось (сопрограмма завершилась),
она выбросит исключение StopIteration, которое воспринимается как сигнал к завершению
цикла.
def f():
for i in range(3):
x = yield i * i
print('получено', x)
>>> coro = f()
>>> coro.send(None)
0
>>> coro.send(11)
получено 11
1
>>> coro.send(True)
получено True
4
>>> coro.send('test')
получено test
Traceback (most recent call last):
File "", line 1, in
StopIteration
Другими словами, генераторное выражение хранится в виде вызванной, но не завершенной
функции, и занимает примерно столько памяти, сколько требуется на хранение самого функционального
объекта и всех локальных переменных вызванной функции.
С range дела обстоят немного иначе. Это объект, который хранит три значения – начало, конец и шаг
и на их основе позволяет вычислить любое значение из диапазона по формуле
ri = начало + i ∙ шаг
или
ri = конец + i ∙ шаг
если индекс отрицательный.
А при взятии среза создается новый объект range
>>> r = range(0, 1000000, 1000)
>>> r[0]
0
>>> r[-1]
999000
>>> r[1:10]
range(1000, 10000, 1000)
>>> r[::-1]
range(999000, -1000, -1000)
Когда такой объект передается в for, создается итератор, который дополнительно хранит
еще и индекс текущего элемента.
>>> r = range(3)
>>> it = iter(r)
>>> it
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
Traceback (most recent call last):
File "", line 1, in
StopIteration
Т.е. range, так же как и генераторное выражение не нуждается в том, чтобы хранить
все значения в памяти, он просто высчитывает очередное значение при каждом обращении
Ответ 2
Размер занимаемый генератором в памяти, не должен сильно меняться.
Пример:
In [119]: gen = (num for num in range(10**100000))
In [120]: sys.getsizeof(gen)
Out[120]: 88
In [121]: gen.__next__()
Out[121]: 0
In [122]: gen.__next__()
Out[122]: 1
In [123]: gen.__next__()
Out[123]: 2
In [124]: sys.getsizeof(gen)
Out[124]: 88
In [125]: for i in range(10000):
...: gen.__next__()
...:
In [126]: sys.getsizeof(gen)
Out[126]: 88
Ответ 3
Генераторное выражение, это, по сути, просто итератор (то есть то, что идёт после
in) плюс информация о том, что нужно сделать с очередным элементом (то есть часть ...
for ... и, если она есть, то ещё часть с if).
То есть когда от генератора требуется очередной элемент, ему нужно просто дернуть
очередной элемент из итератора, проверить, что оно совпадает с условием if (если оно
есть), и выполнить какую-то обработку, которая описана в ... for ....
Соответственно, никакой дополнительной памяти не нужно в процессе перебора элементов
генератора.
#cpp #cpp11
Есть простенький код
typedef int typeint1;
typedef int typeint2;
std::cout << std::is_same::value << std::endl; //true
std::cout << std::is_same::value << std::endl; //true
Есть ли стандартная шаблонная магия, чтобы проверять сходтсво/различие на уровне
имён псевдонимов? Что-то типа:
std::cout << std::is_same_typedef::value << std::endl; //false
std::cout << std::is_same_typedef::value << std::endl; //true
Ответы
Ответ 1
Простое сравнение разных имен реализовать несложно, достаточно сделать stringize:
#include
#include
#define IS_SAME_NAME(A_fist_type, A_second_type) \
(not ::std::strcmp(#A_fist_type, #A_second_type))
int main()
{
typedef int typeint1;
typedef int typeint2;
std::cout << IS_SAME_NAME(typeint1, typeint2) << std::endl; //false
std::cout << IS_SAME_NAME(typeint1, typeint1) << std::endl; //true
return 0;
}
Ответ 2
Вряд ли это возможно, ведь int, typeint1 и typeint2 означают один и тот же тип.
Ответ 3
Такое не возможно. Дело в том, что псевдоним не является типом сам по себе, он еще
одно обозначение для типа. От сюда следует что std::is_same (как и ни что другое в
плюсах) не различает псевдонимы, а только типы.
Ответ 4
Это скорее всего не возможно. Потому что typedef1 и typedef2 неявно преобразовываются
в int. Таков стандарт С++. Но, попробуйте использовать strong typedef, у них такой
проблемы нету.
#c_sharp #base64
Какие в c# есть варианты кодирования последовательности байт в строковую форму, кроме
base64?
Вариант с base64 устраивает почти всем, но у него в символах алфавита используется
несколько неудобных знаков. Мне мешает символ '=', ещё на википедии упоминается, что
возможны проблемы с передачей base64-кодированной строки в url.
Как возможный вариант замены рассматриваю base58, которая упоминается там же на википедии
и которая используется в некоторых биткоин-прокотолах. У неё на выходе возможны только
варианты букв и цифр. Жаль, что в C# включили именно base64, а не base58, придётся
подключать какой-нибудь пакет.
Есть ли какие-то ещё варианты? Есть ли допустим base32 или base16?
Ответы
Ответ 1
Просто в голову пришла вот такая мысль
var str = "Hello, World!";
var encoded = HttpUtility.UrlEncode(
Convert.ToBase64String(Encoding.Default.GetBytes(str)));
Console.WriteLine(encoded);
var decoded = Encoding.Default.GetString(
Convert.FromBase64String(HttpUtility.UrlDecode(encoded)));
Console.WriteLine(decoded);
Ответ 2
Можно каждый байт кодировать как 16-ричное число (2 символа).
Пример:
255 = 'FF'
165 = 'A5'
0 = '00'
и т.д.
#java #android
Требуется сделать TextView. Есть количество символов. Если оно больше (к примеру)
200, то создается кликабельный текст "показать полностью", по клику которого открывается
полный текст. Как реализовать подобное?
Ответы
Ответ 1
Как вариант, можно при создании textView задавать обрезанный текст, дописывая в конце
"показать полностью...", а затем повесить на него слушатель нажатия, по которому текст
будет становиться полным. Что-то вроде:
<...> //OnCreate
TextView textView = findViewById(R.id.textView);
//Получаем полный текст
String fullText = getResources().getString(R.string.text);
String showContent = "Показать полностью...";
int maxLength = 200;
//При необходимости обрезаем и вешаем слушатель
if (fullText.length() > maxLength) {
fullText = fullText.substring(0, maxLength - showContent.length()) +
showContent;
textview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((TextView) v).setText(getResources().getString(R.string.text));
}
});
}
textView.setText(fullText);
<...>
#python #pandas #dataframe #matplotlib #seaborn
Загружаю данные из датасета iris:
from sklearn import datasets
data = datasets.load_iris(return_X_y=False)
X = data.data
y = data.target
names = data.target_names
Датафрейм со всеми данными и целевой переменной в y:
dfy = pd.DataFrame(y)
df = pd.DataFrame(X)
dfy = dfy.rename(columns={0: 'y'})
df_ = pd.concat([df,dfy], axis = 1)
sns.pairplot(df_, hue = 'y')
Несколько боксплотов в одной картинке без классов выводится:
plt.figure(figsize=(14,7))
sns.boxplot(data=df_.drop(['y'], axis=1), palette=sns.color_palette('Greens'))
plt.show()
А несколько бохплотов с классами из столбца y смогла вывести только так:
for i in range(4):
sns.boxplot(data=df_, x ='y', y = i, hue='y')
plt.show()
Как вывести несколько бохплотов с классами в одной картинке?
Ответы
Ответ 1
df = (pd.DataFrame(
data.data,
columns=data.feature_names)
.assign(target=data.target))
d = (df.set_index("target")
.stack()
.reset_index(name="val")
.rename(columns={"level_1":"feature"}))
sns.boxplot(x="feature", y="val", hue="target", data=d)
или так:
sns.boxplot(x="feature", y="val", data=d)
#python
К примеру, у меня в файле запись:
"['1', '2', '3']"
При чтении данных из файла и выводе первого значения списка [0], выводится первый
символ строки [, а не значение списка, то есть строка из файла автоматически преобразуется
в переменную типа str.
Ответы
Ответ 1
воспользуйтесь ast.literal_eval()
import ast
list_ = ast.literal_eval("['1', '2', '3']")
из файла:
import ast
with open(filename) as f:
data = ast.literal_eval(f.read())
PS если же в файле будет сохранен корректный JSON файл, то можно будет воспользоваться
json.load() / json.loads(), но в вашем случае используются одинарные кавычки для обрамления
строк- это нарушает правила JSON.
Ответ 2
s = "['1', '2', '3']"
print(type(eval(s)))
#алгоритм #delphi #pascal
Программу написать скорее всего смогу, но сам принцип решения мне немного не понятен.
Время, которое показывают часы, задано в часах, минутах и секундах. Определите, через
сколько секунд часовая и минутная стрелки совместятся.
Ответы
Ответ 1
Угловая скорость минутной стрелки - 0.1 градус/сек, часовой - (0.1/12) градус/сек.
Угол (по часовой стрелке) между минутной и часовой стрелками зависит от их положения,
то есть от заданного времени.
Разделите этот угол на разницу угловых скоростей.
#java #многопоточность
Помогите разобраться с многоядерной обработкой Java-программы.
Правильно ли я понимаю, что при использовании класса Thread и интерфейса Runnable
Java-программа будет использовать многопоточность только на одном ядре центрального
процессора, при наличии других ядер?
А для реализации многоядерной обработки Java-программы необходимо использовать специализированные
Java-классы, например, Fork/Join Framework?
Ответы
Ответ 1
Нет, не правильно. Java уже давно использует нативные нити. А раскидкой по ядрам
занимается уже сама операционная система.
Так что, даже при использовании Thread и Runnable ваши нити могут быть разбросаны
операционной системой по разным ядрам.
Тут вообще вопрос больше концептуальный. fork - создаёт дочерний процесс, а у него
внутри уже свои нити. Следовательно, fork потяжелее будет. Форкать лучше, если вы хотите
запустить, по сути, копию задачи.
#sql #oracle #oracle11g
Как получить самую последнюю запись из таблицы?
Например, в таблице есть такие идентификаторы:
1
2
7
3
10
5
Последняя запись здесь с идентификатором 10.
Из известных составляющих выражения - это имя таблицы. При этом подразумеваем, что
поиск нужен по первому столбцу который Primary Key и хранит идентификаторы.
Иденитификатор для каждой таблицы создается триггером, который при вставке записи
формирует Id для этой записи. Имена колонок с идентификатором отличаются и заранее
неизвестны, поэтому запрос вообще не должен быть привязан к именам колонок.
Идентификаторы создаются последовательностями, где только CYCLE_FLAG=N.
Вот что я использую (меняю только имя таблицы):
select a.* from (
select rownum rnum, MESSAGES.*
from MESSAGES
) a
where rnum=(select count(1) from MESSAGES);
Пример работает и я получаю в ответ одну строку, которая иногда является записью
с самым последним Id в таблице, а в некоторых таблицах этот запрос не выдает последнию
запись, как если бы первое поле таблицы не было отсортировано по порядку.
Ответы
Ответ 1
Если только первая колонка содержит идентификатор, то надо так:
select t.*
from table_name t
order by 1 desc
fetch first row only;
Для версий <12.1 (опробовано на 11.2.0.4) попробуйте так:
with table_name as (
select to_number (trim (column_value)) id, 'item '||rownum name
from xmltable ('1,2,7,3,10,5')
)
-- здесь начинается запрос
select * from (
select t.*
from table_name t
order by 1 desc
) where rownum = 1;
Результат:
ID NAME
---------- -----------
10 item 5
PS Убедитесь, что используется опция NOCYCLE в генераторах последовательностей.
#cpp #dll #lib #namespace #const
Есть статическая библиотека (.lib/.a).
В этой библиотеке находится файл с namespace, в котором две const переменные с публичным
и приватным ключом:
namespace dsa
{
const std::vector private_key = {...}
const std::vector public_key = {...}
}
Публичный ключ используется в динамической библиотеке (.dll/.so), путем подключения
исходной статической библиотеки.
Приватный ключ используется в исполняемом файле, путем подключения исходной статической
библиотеки.
Поскольку статическая библиотека является слепком .obj файлов единиц трансляции,
то оба ключа будут в ней, это понятно.
А вот будет ли в публичную динамическую библиотеку (.dll/.so) попадать информация
о приватном ключе, если в ней не вызываются функции, использующие его?
Как вообще организовано хранение подобных данных (глобальные const НЕ POD данные)
в windows/linux файлах динамических библиотек?
Ответы
Ответ 1
Да в *.dll попадут оба ключа. В этом отношении, линковка dll ни чем не отличается
от exe. Проверить наличие переменной можно попросив линкер генерировать map файл.
Линкер может выкинуть (при подключении .lib файла), только единицу трансляции целиком
(соответствующею одному .obj/.cpp, из тех, что попали в .lib), и только в случае, если
нет ссылок ни на один символ из этой единицы трансляции. Но ссылка на публичный ключ
используется в любом случае...
Самый надежный способ - написать две статические либы: с приватным и с публичным
ключами по отдельности, тем более, что они должны обеспечивать разную функциональность:
передача и прием сообщений.
Ответ 2
Исходя из ответа @Chorkov провел несколько тестов с использованием /MAP и результаты
огорчили.
Решил хранить приватный ключ в отдельном файле, исключив его таким образом из кода
вообще.
#python
N = int(input())
N = str(N)
kr3 = []
for i in range (len(N)):
for j in range (1,10):
N[i] = N[i].replace (N[i], str(j))
if int(N) % 3 == 0:
kr3.append (int(N))
print (max(N))
Формат входных данных
В первой строке записано натуральное число, не превышающее 10^100
.
Формат выходных данных
Выведите наибольшее число, кратное трём, отличающееся от исходного ровно одной цифрой.
Пример
стандартный поток ввода стандартный поток вывода
123 723
Выдает ошибку: str object does not support item assignment.
Ответы
Ответ 1
Основной посыл: число кратно трем, если сумма цифр в нем кратна трем.
def find_max(value):
data = list(value)
for index in range(len(data)):
if data[index] != '9':
tmp = data[index]
data[index] = str(9 - sum(map(int, data[:index] + data[index + 1:])) % 3)
result = ''.join(data)
if result > value:
return result
data[index] = tmp
return value[:-1] + '6'
print(find_max('123')) # 723
print(find_max('7000')) # 9000
print(find_max('1111')) # 9111
print(find_max('93556')) # 98556
print(find_max('1')) # 9
print(find_max('999')) # 996
Ответ 2
может, проще будет сделать так:
b = '123'
variants = [[int(b[:y]+str(x)+b[y+1:]) for x in range(int(b[y]),10)] for y in range(len(b))]
res = max(set([(x if x%3==0 else 0) for y in variants for x in y]))
print(res)
723
UPDATE
Как было отмечено в комментарии,код выше неверно отрабатывается пограничные значения.
Дополнил:
b = '999'
variants = [[int(b[:y]+str(x)+b[y+1:]) for x in range((int(b[y]) if b[y]!='9' else
1),10)] for y in range(len(b))]
res = max(set([(x if x%3==0 else 0) for y in variants for x in y])-set([int(b)]))
print(res)
996
Ответ 3
def max_multiple_of_three(number):
remainder = int(number) % 3 #(1)
need_to_three = (3 - remainder) #(2)
for digit in number:
new_digit = need_to_three + int(digit) #(3)
multiplier = (9 - new_digit) // 3 #(4)
new_digit += multiplier * 3 #(5)
if digit != '9':
return number.replace(digit, str(new_digit), 1) #(6)
return number[:-1] + '6'
Логика решения следующая:
Чтобы выяснить, сколько числу не хватает до кратности трём, узнаём остаток от деления
на 3 - выражение #(1) и вычитаем его из 3 - выражение #(2).
Признак делимости на три - "Число делится на 3, если сумма всех его цифр делится
на 3". Следовательно, мы можем сделать число кратным 3, прибавив нехватающее значение
(полученное в предыдущем шаге) к любой цифре этого числа - #(3). А так как нам нужно
максимальное число, то прибавлять мы должны к цифре с самым большим разрядом.
Тут есть одна загвоздка: мы можем заменить цифру, сделав число кратным трём, но не
получив при этом максимального числа.
Например, имеем число 121. Ему до кратности трём не хвает 2. Прибавляем 2 к цифре
1 и получаем число 321. Но это число не является максимальным. Максимальным в этом
случае будет 921. Для получения правильного результата, необходимо после выполнения
шага №2, продолжать увеличивать целевую цифру на 3 до тех пор, пока эта цифра меньше
или равна 9. Я сделал это, вычислив количество добавляемых 3 - #(4) и далее применив
этот множитель - #(5).
Как только подходящая цифра найдена, заменяем её в исходной строке и возвращем результат
- #(6).
Другой вариант решения. Суть таже, только вместо 3 используем 9.
def max_multiple_of_three(number):
remainder = int(number) % 9
for digit in number:
new_digit = int(digit) + 9 - remainder
if new_digit > 9:
new_digit -= 3
elif new_digit < 7:
new_digit += 3
if digit != '9':
return number.replace(digit, str(new_digit), 1)
return number[:-1] + '6'
Тесты:
print(max_multiple_of_three('0')) # 9
print(max_multiple_of_three('1')) # 9
print(max_multiple_of_three('9')) # 6
print(max_multiple_of_three('11')) # 81
print(max_multiple_of_three('20')) # 90
print(max_multiple_of_three('50')) # 90
print(max_multiple_of_three('123')) # 723
print(max_multiple_of_three('7000')) # 9000
print(max_multiple_of_three('1111')) # 9111
print(max_multiple_of_three('93556')) # 98556
print(max_multiple_of_three('999')) # 996
#c_sharp #массивы
Узнал что массивы в C#-это типы ссылок и они хранятся в куче,которая используется
для динамичного выделения памяти.Но вот вопрос:для чего массиву динамичное выдиление
памяти?.Вот например мы объявляем массив
int[] newArray = new [4];
Мы заранее знаем что массив будет принимать 4 елемнта типа Int32 и мы заранее знаем
сколько памяти ему потребуется.Так почему массивы-типы ссылок?
Ответы
Ответ 1
"Сколько памяти потребуется" важно не столько при выделении памяти, сколько при хранении
массива в других объектах.
Например, у вас есть класс вида
class A
{
public int fieldA;
public int fieldB;
}
И есть работающий с ним код вида
var a = new A();
a.fieldB = 42;
Перед реальным выполнением этот код надо превратить в код для конкретной платформы.
JIT компилятор, который этим занимается, заранее знает, сколько объект типа A занимает
в памяти, и по какому смещению в нем лежит поле fieldB:
[0 header][+24 fieldA][+28 fieldB] // 24 - условный размер заголовка
и он генеренирует что-то вроде
mov [a + 28], 42 // положить по адресу a + смещение в нем поля fieldB значение 42
И все это работает быстро. Теперь добавим поле-массив (в котором может лежать массив,
а может и не лежать):
class A
{
public int fieldA;
public int[] fieldArray;
public int fieldB;
}
Получаем объект вида
[0 header][+24 fieldA][+28 fieldArray][+32 fieldB] // размер fieldArray предсказуем,
т.к. массив - ссылочный тип, и в этом поле лежит адрес массива.
и код при выполнении
mov [a + 32], 42 // положить по адресу a + смещение в нем поля fieldB значение 42
Ок, теперь представим что int[] - это value type.
[0 header][+24 fieldA][+28 fieldArray][+??? fieldB] // размер fieldArray заранее
неизвестен
Как теперь в этой ситуации записать значение в fieldB? Реально проверять размер массива
перед каждым обращением в соседнее поле? Перекомпилировать метод из IL в C# заново
под каждый объект? Дорого, сложно и неэффективно. Разрешить массивы (и, соответственно,
строчки) только заранее известной длины? Ну тогда на языке вообще будет тяжело что-то
реальное написать :)
А вот если убрать необходимость как-то хранить массивы в других объектах - то все
ок, можно делать из них value type. Именно так сделано для структуры Span, которая,
по сути, и есть value type array.
Вот, выделяет 100 байт чистейшего стека, без всяких там ссылок:
Span stackSpan = stackalloc byte[100];
Ответ 2
На вопрос "Почему?" краткий ответ таков: потому что на данный момент так сделано.
Можно ли сделать иначе: если массив умещается на стеке - размещать его там, не умещается
- размещать в куче? Да, можно. В JVM делается именно так (во всяком случае, в некоторых
реализациях HotSpot). Почему не сделано в CLR? Не всё сразу. Разработчики .NET предпочли
реализовывать другие фичи (значимые типы, дженерики, указатели на неуправляемую память
и пр.)
Однако, работы по определению, где выгоднее разместить объекты, ведутся. Object Stack
Allocation. Надеюсь, эти теоретические работы перейдут в практическую плоскость.
Ответ 3
Потому что можно сделать так:
int[] i;
i = new int[15];
//тут какое либо использование
i = new int[25];
//ещё что либо
n = int.Parse(Console.ReadLine()/*Любой другой способ получения информации от пользователя*/)
i = new int[n];
//ещё что либо
А если быть более честым, то c# полностью объектно-ориентированный, и всё что в нём
есть - объект, а объект - это составная сущность которая занимает (зачастую) неопределённое
количество памяти.
Мы заранее знаем что массив будет принимать 4 елемнта типа Int32 и мы заранее знаем
сколько памяти ему потребуется.
Да и тут я бы с вами поспорил. А как же вычисление значений не на этапе компиляции,
а в рантайме?(во время выполнения)
Простой пример, который я часто использую: мне бывает лень объявлять масивчики и
я пользуюсь таким методом(читай: отрывок паттерна Фабрика. хоть вообще не красивый,
не правильный и нельзя так делать, но блин удобно)
GetArr(int lenght)=> new T[lenght];
Это универсальный метод для создания Массива любого типа.
А ещё, небольшая разница между тем же самым Int32. Это не класс а структура, а структуры
являются TypeValue - значениями, и соответственно хранятся в стеке, а Array является
производным от Object, и соответственно располагается в Куче
#python #python_3x #указатели #ссылка
Сегодня буду краток. Есть код:
a, b, c = 1, 2, 3
arr = [a, b, c]
for i in range(3):
arr[i] += 1
print(a, b, c) # output: 1 2 3
А мне нужно output: 2 3 4. Как можно, изменяя элементы в списке, изменить элементы,
которые были добавлены изначально? Что-то вроде ссылки и указателя?
UPD: я значительно упростил код, поэтому дам некоторые уточнения: так называемые
переменные a, b и c являются атрибутами класса, и я сомневаюсь, что можно решить проблему
через globals()
Ответы
Ответ 1
Выражение arr[i] += 1 соответствует: arr[i] = arr[i] + 1 что переписывает ссылку,
на новую (с новым значением), поэтому ваш код и не работает.
Вообще a, b, c = 1, 2, 3 означает, что переменные a, b, c хранят ссылки на объекты
1, 2, 3. А тут arr = [a, b, c] вы не ссылки на переменные положили, а сами ссылки на
объекты 1, 2, 3.
Вам проще к самим переменным обратиться и поменять значением, чем так. Либо оставить
значения в словаре или в списке и работать с ними.
Но если очень хочется, можно рефлексией поменять у переменных:
a, b, c = 1, 2, 3
arr = [a, b, c]
for i in ['a', 'b', 'c']:
globals()[i] += 1
print(a, b, c) # 2 3 4
и я сомневаюсь, что можно решить проблему через globals()
Через globals() и вправду не получится, т.к. оно меняет глобальные переменные, а
вот для изменения в объектах использовать getattr и setattr:
class Foo:
a, b, c = 1, 2, 3
foo = Foo()
arr = [foo.a, foo.b, foo.c]
for i in ['a', 'b', 'c']:
x = getattr(foo, i)
setattr(foo, i, x + 1)
print(foo.a, foo.b, foo.c) # 2 3 4
Ответ 2
Kогда мне нужно обеспечить изменение объекта "по ссылке", я применяю такой способ:
a, b, c = [1], [2], [3]
arr = [a, b, c]
for i in range(3):
arr[i][0] += 1
print(a[0], b[0], c[0]) # output: 2 3 4
Объяснение.
Немного общей теории:
Объекты числового типа неизменяемы, к такому объекту нельзя прибавить единицу, можно
только создать новый числовой объект с нужным значением и заменить на него исходный.
Соответственно:
а = 1 означает: создай объект со значением 1 и помести его в глобальный словарь с
переменными (globals) под именем a.
а = a + 1 означает: найди в словаре с переменными объект под именем a, сложи его
с объектом 1, результат запиши в новый объект 2. В глобальном словаре замени значение
a ссылкой на этот объект.
a, b, c = 1, 2, 3 - создай три числовых объекта, запиши их ссылки в словарь с переменными
под именами a, b, c, соответственно. Тут ещё задействованы кортежи, но про них не буду
говорить, чтобы не усложнять.
Объекты типа list изменяемы, в список можно добавлять и удалять значения, можно менять
уже находящиеся в списке. Список хранит не сами объекты, а ссылки на них, меняя значение
в списке, мы на самом деле заменяем ссылку предыдущего объекта на новую, указывающую
на другой объект.
arr = [a, b, c] - создай объект типа список и наполни его ссылками на объекты, которые
хранятся в словаре с переменными под именами a, b, c. Какая ссылка хранится под именем
a? Ссылка на числовой объект 1. Под именем b ссылка на 2 и т. д. Таким образом, имеем
arr = [1, 2, 3] - список arr не хранит ни самих переменных, ни информации из каких
переменных объекты 1, 2, 3 были получены. Кстати, теперь каждый из трёх объектов 1,
2, 3 имеет на себя как минимум по две ссылки - одна в глобальном словаре с переменными
(a, b, c), другая внутри списка arr.
Когда вы делаете arr[0] += 1, вы берёте из списка нулевой элемент, который представляет
из себя ссылку на числовой объект 1 и прибавляете к этому объекту единицу. Информации
про переменную, с помощью которой вы этот объект назначали, в списке нет. Результат
(ссылку на новый объект) записываете обратно в нулевой элемент списка.
Использование списка для сохраненения ссылки на значение переменной:
a, b, c = [1], [2], [3] - оборачиваем каждый числовой объект в список и пишем ссылку
на этот список в переменную. Помним, что объект типа список хранит не сам числовой
объект, а ссылку на него. Следовательно, под именем a у нас хранится ссылка на список,
который содержит единственный элемент - ссылку на объект 1.
arr = [a, b, c] - эту строчку можно представить как arr = [[1], [2], [3]]. Информацию
о переменных a, b, c мы потеряли также, как и в предыдущем случае, однако сейчас и
переменная a, и arr[0] указывают на список [1]. И этот список содержит нужное нам значение,
которое мы можем менять, сохраняя в a и arr[0] ссылку на список-обёртку.
arr[0][0] += 1 - возьми нулевой элемент из списка. В нашем случае это [1]. Возьми
и у него нулевой элемент. Это будет числовой объект 1. Прибавь к нему единицу. Получившимся
новым объектом замени нулевой элемент в списке [1]. Список мы не трогаем, а лишь меняем
внутри него элемент на другой. Ссылка на список остаётся неизменной, переменная a продолжает
на него указывать, только теперь этот список содержит 2 вместо 1.
Мой ответ на похожую тему.
В мануале на английском этот способ под № 3: How do I write a function with output
parameters (call by reference)?.
Ответ 3
a, b, c = 1, 2, 3
arr = [a, b, c]
a, b, c = map(lambda x: x+1, arr)
print(a, b, c)
2 3 4
#javascript #canvas
Я пытаюсь реализовать при помощи canvas функционал стирания изображения ластиком.
Я создаю canvas и задаю ему background в CSS. Поверх canvas я делаю drawImage png
картинки с прозрачностью, к которой я применяю ластик. Мне нужно проверить, стерта
ли картинка полностью, то есть полностью ли прозрачный фон, и осуществить дальше какое-то
действие.
Мой метод создания канваса, отрисовки png на нем и процесса стирания:
var img = new Image;
var canvas = {};
function createCanvas(parent, width, height) {
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
img.onload = function(){
canvas.context.drawImage(img,200,0,img.width*1.2,img.height*1.2); // Or at whatever
offset you like
};
img.src = 'raccoon.png';
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 80; // or whatever
var fillColor = '#000000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
if (isFullyTransparent()) {
redirect();
};
};
}
function isFullyTransparent() {
var d = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i=3; i < d.length; i+=4)
if (d[i])
return false
return true
}
function redirect() {
};
var container = document.getElementById('canvas');
init(container, 1024, 768, '');
Картинка для примера. Нужен метод, проверяющий, стерт енот полностью или нет.
Ответы
Ответ 1
Можно проверить все пиксели на прозрачность при помощи их перебора и поиска не 0
значения:
Рисовать левой кнопкой мыши, стирать - правой
var img = new Image;
var canvas = {};
function createCanvas(parent, width, height) {
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
img.onload = function() {
canvas.context.drawImage(img,0,0,img.width,img.height);
canvas.context.globalCompositeOperation = 'destination-out';
};
img.crossOrigin = "anonymous";
img.src = 'https://i.imgur.com/GtBHNPS.png';
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing)
return;
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 80;
var fillColor = '#fff';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
if (isFullyTransparent()) {
redirect();
};
};
}
function isFullyTransparent() {
var d = canvas.context.getImageData(0, 0, canvas.node.width, canvas.node.height).data;
for (var i=3; i < d.length; i+=4)
if (d[i])
return false
return true
}
function redirect() {
alert('redirect')
}
init(document.body, 350, 350);
body{
background: #000a;
}
#python #python_3x #for
Накопал в интернете эту ссылку:
https://clck.ru/JccbR
Здесь написано на C++, попытался перевести на Питон, в соразмерности со своими знаниями,
получил:
def test(i):
k = i
while(k):
d = k % 10
k /= 10
if (d and i % d):
return False
return True
n = int(input())
for i in range(1, n + 1):
if (test(i)):
print(i)
Программа ничего не выводит, подскажите пожалуйста где я не прав?
Ответы
Ответ 1
В Python 3.x:
k /= 10
Вернет число с плавающей точкой.
Воспользуйтесь целочисленным делением:
k //= 10
def test(i):
k = i
while(k):
d = k % 10
k //= 10
if (d == 0 or i % d):
return False
return True
проверка:
In [174]: for i in range(1, int(input()) + 1):
...: if (test(i)):
...: print(i)
...:
42
1
2
3
4
5
6
7
8
9
11
12
15
22
24
33
36
Ответ 2
Проблема решена, как и сказал @MaxU нужно было заменить k/=10 на k//=10, а также
сделать проверку на круглое число:
def test(i):
k = i
while(k):
d = k % 10
k //= 10
if (d and i % d):
return False
return True
n = int(input())
for i in range(1, n + 1):
if (test(i) and i % 10 != 0):
print(i)
Большое спасибо)
#python #алгоритм #графы
Задача:
Автомобилист хочет проехать от города u до города v, по стране с количеством городов
n. Известны длины дорог между всеми городами, дороги двухсторонние. Автомобиль имеет
ограниченный запас топлива k, в начале пути бак полностью заполнен. Восполнять запас
топлива до максимального k он может в некоторых городах по дороге. Нужно посчитать
сколько минимум нужно будет сделать заправок по дороге чтобы попасть из города u в город v.
Формат входных данных
Первая строка содержит пять целых чисел: k — сколько километров может проехать машина
без дозаправок, n — количество городов, m — количество дорог, u — номер города начала
дороги, и v — номер города, куда нужно доехать (1 ≤ k ≤ 500, 2 ≤ n ≤ 10 000, 0 ≤ m
≤ 10 000, 1 ≤ u,v, ≤ n, u ≠ v).
В следующих m строках задаются дороги. В i-й из этих строк записаны три числа p_i,
q_i, r_i —
номера двух городов, которые соединяет очередная двухсторонняя дорога, и её длина.
(1 ≤ p_i, q_i ≤ n, 1≤ r_i ≤ 10^9)
Следующая строка содержит целое число l — количество заправок (0 ≤ l ≤ n). Наконец,
последняя строка содержит l чисел a_1, a_2, . . . , a_i — номера городов с заправками
в порядке возрастания (1 ≤ a_1 < a_2 < ... < a_l ≤ n).
Формат выходных данных
Выведите -1, если невозможно доехать от города с номером u до города с
номером v, или минимальное количество заправок, если это возможно.
Примеры:
input #1:
3 3 3 1 3
1 2 3
1 3 4
2 3 3
2
2 3
output #1:
1
input #2:
3 3 3 1 3
1 2 2
1 3 4
2 3 2
0
output #2:
-1
input #3:
3 3 3 1 3
1 2 2
1 3 4
2 3 1
0
output #3:
0
Ограничение по времени: 2 секунды;
Ограничение по памяти: 512 мегабайт
Моё решение:
k,n,m,u,v = [int(i) for i in input().split()]
adj = {}
for j in range(m):
p,q,r = [int(i) for i in input().split()]
if p-1 in adj:
adj[p-1].append([q-1,r])
else:
adj[p-1] = [[q-1,r]]
if q-1 in adj:
adj[q-1].append([p-1,r])
else:
adj[q-1] = [[p-1,r]]
l = int(input())
refills = [False] * n
if not l is 0:
for i in input().split():
refills[int(i)-1] = True
count = [0] * n
tank = [None] * n
level = [-1] * n
def bfs(s):
global level,charging,k
level[s] = 0
queue = [s]
tank[s] = k
while queue:
v = queue.pop(0)
for w_ in adj[v]:
w = w_[0]; r = w_[1];
if tank[w] is None:
tank[w] = k
if level[w] is -1 and r<=tank[v]:
level[w] = r+level[v]
if refills[w]:
tank[w] = k
count[w]+=1
else:
tank[w] -=r
queue.append(w)
bfs(u-1)
if level[v-1] is -1:
print(-1)
else:
print(count[v-1])
Я использую поиск в ширину с дополнительными условиями, алгоритм достаточно прост.
Но моё решение выдаёт ошибки на некоторых тестах (входные данные на которых происходит
ошибка я не знаю).
Подскажите, пожалуйста, что не так в алгоритме. Либо посоветуйте иной способ решения.
Ответы
Ответ 1
Задача на самом деле достаточно простая. Давайте посмотрим на ограничения. 10к вершин.
500км запаса хода максимум (!!). Кстати можно сразу убирать дороги длиннее k, всё равно
проехать не сможем.
А теперь самый интересный момент - из 1 вершины {i} сделаем k вершин {(i,d)} которые
будут показывать количество заправок на маршруте от старта к i, при этом в пункте i
осталось d км топлива.
Оценим сложность. 10к * 500 = 5кк. По памяти это около 20 мегабайт. По времени. 5кк
вершин. Количество ребёр в сумме пусть тоже будет 5кк. Алгоритм комбинированного обхода
(или как его правильно) O( (N+M) ) ~ 10kk вполне успевает. Идея алгоритма - идём без
заправок пока можем, но складываем отдельно места где можно заправится. Потом эти места
обрабатываем в порядке очереди.
Ну как бы и всё. Дальше дело техники сделать переход. Из i->j переход возможен только
из вершин где топлива достаточно (обычный цикл от длины до k) без увеличения ответа.
И с увелечением ответа на 1 в k - длину.
Ответ - минимум по всем "размноженным" последним вершинам.
Реализацию проще делать через хранение массива [0,k] в каждой обычной вершине.
Код пока не пишу. Если возникнут вопросы по реализации - помогу.
Ответ 2
Предлагаю решение, похожее на алгоритм Дейкстры. Не уверен, можно ли в принципе уложиться
во временной лимит 2 секунды при использовании Python. Я потестировал это решение на
больших рандомных графах - 6000 городов, 9000 дорог, результаты от 0.8 до 4 секунд
в зависимости от удачности сложения графа.
Я создавал графы для тестирования с помощью модуля networkx, затем переводил их
в нужный для задачи формат. Могу добавить сюда код, если нужно.
Алгоритм
Стартуем из текущего города (в начале это один город - первый, на следующих итерациях
перебираем все конечные города предыдущего заезда) и едем до всех возможных городов
на расстоянии одного бака. Все эти города можно сразу добавлять в ответ - мы уже знаем
количество заправок необходимое, чтобы доехать них.
Проезжая очередной город фиксируем его расстояние до ближайшей заправки в словарь:
если город имеет заправку, то расстояние до заправки = 0.
если не имеет, то пишем расстояние до ближайшего города с заправкой, из уже посещённых.
Города, дальше которых машина не смогла проехать из-за нехватки топлива, запоминаем
- на следующем витке алгоритма будем их заправлять в ближайшем посещённом городе (просто
вычитая расстояние до этого города из стартового запаса хода) и повторять шаги 1, 2, 3.
Другими словами: первая заправка - едем во все стороны, добавляя каждый посещённый
город в ответ. Топливо кончилось - встали в конечном городе. Пошла вторая заправка.
Все вставшие машины заправляем и опять едем до упора. Так мы доберёмся до каждого города
на карте. Или недоберёмся - заправки кончились, искомый город не нашли, возвращаем -1.
Замечание: все дороги, длина которых больше, чем максимальный запас хода (полный
бак) можно исключить в самом начале - на этапе формирования списка смежности.
source.py
def find_shortest_path():
def make_adj_dict(roads_num, max_pos_dist):
adj_dict = {k : {} for k in range(1, roads_num + 1)}
while roads_num > 0:
city_a, city_b, distance = map(int, input().split())
if distance <= max_pos_dist:
adj_dict[city_a][city_b] = distance
adj_dict[city_b][city_a] = distance
roads_num -= 1
return adj_dict
max_possible_distance, cities_num, roads_num, start_city, end_city = map(int,
input().split())
adj_dict = make_adj_dict(roads_num, max_possible_distance)
refuel_num = int(input())
if refuel_num > 0:
cities_with_gs = {int(num) : True for num in input().split()}
else:
cities_with_gs = {}
answers = {}
one_tank_reachable_cities = set()
one_tank_reachable_cities.add(start_city)
should_be_refueled_set = set()
dist_to_last_gs = {k : 0 if k in cities_with_gs else float("inf") for k in range(1,
cities_num + 1)}
fuel_left_dict = {k : 0 for k in range(1, cities_num + 1)}
fuel_left_dict[start_city] = max_possible_distance
for refuel_cnt in range(refuel_num + 1):
if should_be_refueled_set:
for city in should_be_refueled_set:
fuel_residue = max_possible_distance - dist_to_last_gs[city]
if fuel_residue >= 0:
fuel_left_dict[city] = fuel_residue
one_tank_reachable_cities.add(city)
should_be_refueled_set = set()
while one_tank_reachable_cities:
city_a = one_tank_reachable_cities.pop()
answers[city_a] = refuel_cnt
for city_b, a_to_b_dist in adj_dict[city_a].items():
dist_to_last_gs[city_b] = min(dist_to_last_gs[city_a] + a_to_b_dist,
dist_to_last_gs[city_b])
if city_b in answers:
continue
fuel_before_ride = fuel_left_dict[city_a]
if a_to_b_dist <= fuel_before_ride:
one_tank_reachable_cities.add(city_b)
fuel_after_ride = fuel_before_ride - a_to_b_dist
fuel_left_dict[city_b] = max(fuel_after_ride, fuel_left_dict[city_b])
else:
should_be_refueled_set.add(city_a)
return answers[end_city] if end_city in answers else -1
Тестирование
cnt = 1
while True:
try:
print(find_shortest_path(), end='')
print(f"\t#Case № {cnt}")
except EOFError:
break
cnt += 1
input.txt
### Case № 1, output = 1
3 3 3 1 3
1 2 3
1 3 4
2 3 3
2
2 3
### Case № 2, output = 0
3 3 3 1 3
1 2 2
1 3 4
2 3 1
0
### Case № 3, output = -1
3 3 3 1 3
1 2 2
1 3 4
2 3 2
0
### Case № 4, output = 3
50 7 8 1 7
1 2 50
1 3 50
1 4 50
2 5 50
3 5 60
4 5 40
5 6 40
6 7 30
4
2 3 5 6
### Case № 5, output = 1
120 7 8 1 7
1 2 50
1 3 50
1 4 50
2 5 50
3 5 60
4 5 40
5 6 40
6 7 30
2
2 3
Строки начинающиеся с ### нужны для наглядности, перед запуском программы их надо
убрать. Я их не удаляю из файла input.txt вручную, а пропускаю через sed перед подачей
на ввод программы (пользуюсь Ubuntu):
./source.py < <(sed '/#/d' input.txt)
Output
1 #Case № 1
0 #Case № 2
-1 #Case № 3
3 #Case № 4
1 #Case № 5
#cpp #циклы
Можно ли заменить следующий бесконечный цикл на обычный цикл? Слышал, что всегда
можно, но не понимаю как.
while (true) {
if (c1(a)) {
a = f1(a);
}
if (c2(a)) {
break;
}
a = f2(a);
}
Здесь f1, f2 - функции, возвращающие какое-то значение, зависящее от a, c1, c2 -
условия (функции, возвращающие bool), зависящие от a.
upd:
под обычным я понимаю без break, continue, goto и прочих хаков, а чтобы условие было
не постоянным/пустым
Ответы
Ответ 1
Заменить можно так
do {
if (c1(a)) {
a = f1(a);
}
cond = !c2(a);
if (cond)
a = f2(a);
} while (cond);
но в данном случае бесконечный цикл нагляднее
Ответ 2
Например можно так. Но я бы не сказал что это улучшит читабельность.
for (;!c2(a=!c1(a)?:f1(a));a=f2(a));
Внезапный код-гольф?
Ответ 3
Если вы хотите for (обычный) - то можно просто
for(;;) {
if (c1(a)) {
a = f1(a);
}
if (c2(a)) {
break;
}
a = f2(a);
}
Или
for(;;a = f2(a)) {
if (c1(a)) a = f1(a);
if (c2(a)) break;
}
Мне кажется, что так понятнее всего.
Ответ 4
Если захотите, то можно ещё использовать Go to, но это не советуется использовать.
Главное не забывайте, что нужно условие выхода, оно делается через
if() {
}
Самым практичным является
while (true) {
Тело
}
Либо
for(;;) {
}