Полезное для разработчика

18
Янв
2020

Задача о прогуливающихся джентльменах

Логическая головоломка о прогулке двух джентльменов-близнецов по аллее с ответвлениями. Неизбежна ли встреча?

Эта задача – шестой эпизод нашего сериала головоломок. После описания задачи идёт ответ на преды…

18
Янв
2020

Лучшие IT-выступления 2019 по версии Tproger: веб-разработка

«Алиса» для сайтов и drag&drop-компоненты для людей и нарушением зрения — собрали самые интересные выступления по веб-разработке по версии Tproger.
— Читать дальше «Лучшие IT-выступления 2019 по версии Tproger: веб-разработка»

18
Янв
2020

Мнение разработчика: «Стоп! Kotlin — это не только Android»

IT-рекрутеры и новички в разработке ассоциируют Kotlin почти только с мобильной платформой. Мы собрали несколько мнений, противоречащих сложившейся репутации языка.

Берлинский разработчик Жан-Мишель Файард …

17
Янв
2020

Веб-скрапинг по расписанию с Django и Heroku

Создаём Django-приложение, ежедневно проверяющее доску объявлений о работе. Парсим в BeautifulSoup, сохраняем в PostgreSQL, развёртываем на сервере Heroku.

Веб-скрапинг используется для сбора различной информации, в том числе для таких видов данных, которые регулярно обновляются, например, сообщений с досок объявлений о новых вакансиях. В этом проекте мы развернём на сервере Heroku приложение Django, которое посылает соответствующие уведомления о публикации новых мест работы.


План рассказа:

  1. Создаём Django приложение
  2. Создаём и настраиваем модель вакансии
  3. Настраиваем базу данных
  4. Тестируем приложение
  5. Настраиваем команды django-admin
  6. Разёрываем приложение на Heroku
  7. Планируем расписание скрапинг

1. Создаём Django приложение

Создаём каталог приложения и переходим в него.

            mkdir jobs && cd jobs 
        

Создаём и запускаем виртуальную среду. Устанавливаем необходимые пакеты.

            python -m venv env
source env/bin/activate
pip3 install django psycopg2 django-heroku bs4 gunicorn 
        

Создаём проект Django.

            django-admin startproject jobs 
        

Заходим в проект и создаём приложение для скрапинга.

            cd jobs
django-admin startapp scraping 
        

2. Создаём и настраиваем модель

Теперь нужно определить единственную модель нашего приложения – модель работы. Она соответствует записям о вакансиях, которые мы будем собирать.

Файл /scraping/models.py перезаписываем со следующим содержанием.

            from django.db import models
from django.utils import timezone

class Job(models.Model):
    url = models.CharField(max_length=250, unique=True)
    title = models.CharField(max_length=250)
    location = models.CharField(max_length=250)
    created_date = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['title']
   
    class Admin:
        pass 
        

Зарегистрируем модель в /scraping/admin.py. Это позволит просматривать записи в стандартной панели администратора Django (скоро мы к этому вернёмся):

            from scraping.models import Job
admin.site.register(Job) 
        

Добавялем scraping в установленные приложения в /jobs/settings.py.

            INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'scraping'
] 
        

3. Настраиваем базу данных

Настраиваем базу данных. В нашем примере это будет PostgreSQL (Библиотека программиста писала о том, как начать разбираться в PostgreSQL).

Создаём базу данных для проекта в командной строке. Открываем консоль PostgreSQL:

            psql -d template1 
        

Создаём пользователя и базу данных, выходим:

            create user django_user;
create database django_jobs owner django_user;
\q 
        

В /jobs/settings.py обновите константу DATABASES:

            DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'django_jobs',
        'USER': 'django_user',
        'HOST': '',
        'PORT': ''
    }
} 
        

Создаём файлы для миграции и переносим базу данных.

            python manage.py makemigrations
python manage.py migrate 
        

Это создаст таблицу с именем scraping_job. Название соответствует соглашению Django о пространстве имён.

Создаём суперпользователя и пароль:

            python manage.py createsuperuser --email admin@example.com --username admin 
        

4. Тестируем приложение

Мы уже что-то сделали, но пока понятия не имеем, работает ли оно. Давайте проверим, прежде чем идти дальше:

            python manage.py runserver 
        

Переходом в браузере по адресу http://127.0.0.1:8000/admin. Входим в систему под суперпользователем, которого только что создали. После входа в систему, нажимаем jobs в разделе scraping, затем add job в правом верхнем углу. Заполняем пример информации и жмём save. Если вы видите созданную вами запись, то всё работает.

5. Настраиваем команды django-admin

Теперь настроим кастомную команду django-admin, которая производит скрапинг доски с вакансиями. Это то, что мы планируем на уровне инфраструктуры, чтобы автоматизировать скрапинг.

Внутри каталога /scraping создаём каталог с именем /management и каталог внутри /management с именем /commands. В папке /commands создаём два файла Python: _private.py и scrape.py.


Ниже идёт код скрапера, записанный в scrape.py. При необходимости перепишете его под страницу, с которой нужно собирать информацию. Здесь это вакансии фирмы, в которой автору интересно работать.

            from django.core.management.base import BaseCommand

from urllib.request import urlopen
from bs4 import BeautifulSoup
import jsonfrom scraping.models import Job

class Command(BaseCommand):
    help = "collect jobs"   

    # определяем логику команд
    def handle(self, *args, **options):

        # собираем html
        html = urlopen('https://jobs.lever.co/opencare')

        # преобразуем в soup-объект
        soup = BeautifulSoup(html, 'html.parser')

        # собираем все посты
        postings = soup.find_all("div", class_="posting")

        for p in postings:
            url = p.find('a', class_='posting-btn-submit')['href']
            title = p.find('h5').text
            location = p.find('span', class_='sort-by-location').text        # check if url in db
            try:
                # сохраняем в базе данных
                Job.objects.create(
                    url=url,
                    title=title,
                    location=location)
                print('%s added' % (title,))
            except:
                print('%s already exists' % (title,))

        self.stdout.write( 'job complete' )

 
        

Функция handle в определении класса Command сообщает Django, что это пользовательская команда django-admin. Для самого скрапинга используем BeautifulSoup. В Библиотеке программиста есть популярный видеокурс по парсингу сайтов со ссылками на видео и листингом кода.

Запускаем свежесозданную пользовательскую команду:

            python manage.py scrape 
        

Видим следующий вывод:


Запустив снова, увидим следующее:


Разный вывод связан с тем, что в scrape.py мы запретили добавлять дубликаты записей.

Если у вас установлена ​​программа администрирования баз данных (например, dbeaver), вы также можете проверить строки в БД. Это должно выглядеть приблизительно так, как показано ниже.


6. Развёртываем на Heroku

Перенесём получившийся результат на Heroku. Заморозим зависимости, чтобы Heroku знал, что устанавливать при развёртывании.

            pip3 freeze > requirements.txt 
        

Предотвратим перенос ненужных файлов. В .gitignore запишем следующее:

            .DS_Store
jobs/__pycache__
scraping/__pycache__ 
        

Создаём файл с именем Procfile в корне и вставляем приведённые ниже строки:

            web: gunicorn jobs.wsgi
release: python manage.py migrate 
        

Первая строка говорит Heroku о запуске web dyno, вторая команда переносит базу данных.

Дерево файлов будет выглядеть так.


Заходим в heroku из командной строки (heroku login). Создаём приложение с любым подходящим именем. Имя обязано быть уникальным среди всех приложений Heroku. Вводим heroku create имя-приложения .

Теперь добавляем следующие строки в самый конец файла settings.py. Модуль heroku_django позаботится за вас о настройках конфигурации.

            import django_heroku
django_heroku.settings(locals()) 
        

Обновляем в настройках DEBUG, если не хотим развертывать в режиме отладки.

            DEBUG = False 
        

Добавляет файлы в Git.

            git init
git add . -A
git commit -m 'first commit' 
        

Пушим приложение в Heroku.

            git push heroku master 
        

7. Планируем расписание скрапинга

Конечно, можно вручную запускать задание из командной строки

            heroku run python manage.py scrape 
        

Но мы же хотим автоматизировать процесс! Входим в консоль Heroku, идём в Resources, затем find more add-ons.


Находим и нажимаем на дополнение, ищем scheduler .




Нажимаем, выбираем время, например, everyday at... 12am UTC. Не пингуем сайты больше чем нужно. Вводим созданную команду и сохраняем.


Теперь просто дожидаем 12:00 UTC или другого времени, и проверяем базу данных.

Заключение

Мы коснулись здесь многих разных вещей: Django, Heroku, веб-скрапинг, PostgreSQL. О всех этих инструмента по отдельности Библиотека программиста уже писала, а объединяющего практического материала – ещё не было. Если что-то оказалось сложным, воспользуйтесь приведёнными ссылками.

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

  • Компании электронной коммерции хотят отслеживать цены конкурентов..
  • Разработчики отслеживают IT-мероприятия и курсы из разных источников.
  • Аналитики собирают информацию о конкурсах по анализу данных с нескольких платформ.

Это пособие лишь конкретный пример использования подхода. Дайте нам знать, если вам интересны подобные проекты.

17
Янв
2020

Программирование на Delphi. Часть 2. Разработка Android-приложения

Продолжаем нашу серию статей по Delphi. В предыдущем материале мы установили бесплатную версию Delphi и запустили простейшую программу под Windows, сегодня наша цель: разработать первое приложение на платформе Android и запустить его на своём телефоне….

17
Янв
2020

Наглядная шпаргалка по операциям с DataFrame в pandas для data wrangling и не только

Удобная и наглядная шпаргалка по основным операциям с DataFrame в pandas. Подходит для data wrangling и не только.
— Читать дальше «Наглядная шпаргалка по операциям с DataFrame в pandas для data wrangling и не только»

17
Янв
2020

Почему HSL цвета CSS лучше!

От автора: одним из наиболее фундаментальных понятий в CSS являются цвета HSL. Это базовая концепция, но в этой статье мы сосредоточимся на ее представлении при указании браузерам. В Интернете каждый цвет представляет собой комбинацию из 3 цветов: красный, зеленый и синий. Как каждый пиксель на экране состоит из трех лампочек: зеленой, синей и красной. Наиболее […]

17
Янв
2020

Верстать быстро и красиво: 15 популярных CSS фреймворков

Главные особенности фреймворков для вёрстки CSS. От продвинутых Bootstrap и Foundation до крошечных Milligram и Dead Simple Grid. Помогаем выбрать инструмент для настройки дизайна вашего проекта.

Создание к…

16
Янв
2020

Кейс: реактивный подход в высоконагруженном приложении на примере сервиса для начисления кэшбэка

Компания SimbirSoft рассказывает об особенностях работы с микросервисами и Project Reactor и об основных этапах их разработки.
— Читать дальше «Кейс: реактивный подход в высоконагруженном приложении на примере сервиса для начисления кэшбэка»

16
Янв
2020

Как повысить продуктивность при анализе данных? 25 неочевидных инструментов

Список бесплатных инструментов и библиотек для аналитиков данных. Заслуживающие внимания пакеты, программы и ресурсы, о которых не так часто упоминают, как о NumPy, Pandas или Jupyter.

Ниже представлен сжатый обзор 25 инструментов для самых разнообразных приложений науки о данных. Быстрый скрапинг веб-страниц и визуализация, анализ поведения клиентов и безопасное хранение ключей, работа в команде и развертывание моделей на облачных GPU.

В комментариях к публикации предлагаем поделиться своими любимыми библиотеками и инструментами.

Обзор DS инструментов:

  • Airtable: электронная таблица с мощью базы данных, альтернатива Google Sheets или Microsoft Excel. Отлично работает с Pandas, благодаря Python API. То что нужно для демонстрации результатов.
  • Orange: open source платформа, заточенная под машинное обучение и визуализацию данных, для которой не нужно уметь кодить. Качественная альтернатива Tableau или Power BI.
  • MarkDown: приложение для заметок на Node.js, полноценно работающее в офлайне с возможностью размещения на своём сервере.
  • Deepnote: приложение на базе Jupyter Notebook, созданное для совместной работы в реальном времени.

  • Dash by Plotly: JavaScript инструмент визуализации данных с открытым исходным кодом. Запустите готовую модель на Python или R, а Dash позаботится об остальном. Идеально подходит для создания мелких веб-приложений для показа клиенту.
  • KeeWeb: средство для безопасного хранения API-ключей и паролей.
  • MLxtend (сокр. от Machine Learning Extensions) – библиотека Python инструментов для повседневных задач обработки данных. Создатель – автор книги «Машинное обучение на Python» Себастьян Рашка.
            import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import itertools
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import EnsembleVoteClassifier
from mlxtend.data import iris_data
from mlxtend.plotting import plot_decision_regions

# Initializing Classifiers
clf1 = LogisticRegression(random_state=0)
clf2 = RandomForestClassifier(random_state=0)
clf3 = SVC(random_state=0, probability=True)
eclf = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3],
                              weights=[2, 1, 1], voting='soft')

# Loading some example data
X, y = iris_data()
X = X[:,[0, 2]]

# Plotting Decision Regions

gs = gridspec.GridSpec(2, 2)
fig = plt.figure(figsize=(10, 8))

labels = ['Logistic Regression', 'Random Forest', 
          'RBF kernel SVM', 'Ensemble']

for clf, lab, grd in zip([clf1, clf2, clf3, eclf],
                         labels,
                         itertools.product([0, 1],
                         repeat=2)):
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y,
                                clf=clf, legend=2)
    plt.title(lab)

plt.show() 
        

  • Lifetimes: библиотека для анализа поведения клиентов, прогнозирования прибыли и оттока
  • GitLab: альтернативное GitHub хранилище репозиториев с возможностью скрывать групповые репозитории. Удобно для закрытой командной работы и группового участия в ML-соревнованиях.
  • Draw.io: создания диаграмм для планирования проекта.
  • Spider: простой скраппер для веб-страниц в виде расширения Chrome. Можно скачивать страницы в CSV/JSON формате.
  • Simple Scraper: превратите любой сайт в API.
  • Airbnb Knowledge repo: ресурс для обмена знаниями между специалистами в области обработки данных и других технических профессий. Был создан для решения проблемы распространения знаний в рамках растущей команды.

  • Kyso: сервис помогает создать привлекательное и структурированное портфолио аналитика данных. Вы сможете просматривать чужие портфолио, увидите, как другие представляют себя и свои данные. Бесплатный период 14 дней.
  • LabelImg: графический инструмент для разметки объектов на картинках, добавление подписей и тегов изображений.

  • Reveal.js: фреймворк для создания HTML-презентаций. Многие аналитики используют его на своих выступлениях.
  • PythonAnywhere: простой способ развернуть онлайн лёгкий ML-проект на Python и сопутствующих библиотеках, если пока требуется лишь проверить гипотезу. В случае успеха легко перенести на AWS (руководство).
  • Sheety: превратите Google Sheet в API и моделируйте данные в реальном времени.
  • Jupyterthemes: устали от текущей темы Jupyter Notebook? Есть много других.
  • Light GBM: одна из популярных библиотек для односторонней выборки на основе градиента. В последние годы приобрела большую популярность, особенно на Kaggle.

  • Machine Learning A-Z: Practice Datasets and Codes: большое собрание данных и кода на Python и R, охватывающее популярные алгоритмы машинного обучения.
  • Gradient by Paperspace: запускайте блокноты Jupyter бесплатно на облачной машине, оснащённой графическими процессорами.
  • Glueviz: визуализируйте многомерные наборы данных. Бесплатный инструмент на основе Python (поставляется с Anaconda). Отлично подходит для поиска связей между наборами данных.

  • Hot dog or not hot dog?: мануал, не требующий знаний AI, машинного обучения и даже программирования. Руководство о том, как с IBM Watson написать программу для проверки, является ли объект хот-догом 🌭 или нет. Самый важный ресурс в подборке 😉
  • FloydHub Workspaces: облачная среда разработки для глубокого обучения. Можно запускать блокноты Jupyter, скрипты Python, использовать терминал и многое другое.

О чём-то не упомянули? Напишите, мы дополним статью вашими ссылками

16
Янв
2020

Цитирование в HTML

От автора: слишком часто можно увидеть неправильный HTML-код, используемый для цитат в разметке. В этой статье давайте разберемся со всем этим, рассмотрим различные ситуации и разные HTML-теги для этих ситуаций. В цитатах используются три основных элемента HTML: <blockquote>, <q>, <cite>. Давайте рассмотрим их по порядку. blockquote Теги blockquote используются для того, чтобы цитируемый текст отличался […]

15
Янв
2020

Опыт разработки: почему мы пишем инфраструктуру машинного обучения на Go, а не на Python

Разработчик Cortex Калеб Кайзер делится соображениями о преимуществах применения Go для инфраструктурных решений в ML-проектах и о том, как два языка могут дополнять друг друга.

Python – самый популярный яз…

15
Янв
2020

Как программисту создать картинку без Фотошопа

Нужны уникальные картинки, но рисовать — слишком муторно и сложно? Пусть это сделает алгоритм. Рассказываем про generative art — искусство программистов.
— Читать дальше «Как программисту создать картинку без Фотошопа»

15
Янв
2020

Онлайн: обучение Java-разработке с оплатой после трудоустройства

Учебная программа по современному стеку веб-разработки на Java. Главная особенность — не придётся ничего платить, пока не найдёте первую работу в Москве.
— Читать дальше «Обучение Java-разработке с оплатой после трудоустройства»

15
Янв
2020

Задача с собеседования + идеи проекта: «Время великих учёных»

В новой задаче ответом является алгоритм, а не число. Есть что обсудить. Если вы найдёте алгоритм, то сможете использовать его в предложенных проектах выходного дня.

Эта задача – пятый эпизод нашего сериала головоломок. После описания задачи идёт ответ на вчерашнюю головоломку о фамилии Тьюринга.

Задача об эпохе выдающихся учёных

Собеседование. Редактор издания «История Всемирной науки» нанимает программиста. Тестовое задание: выяснить интервал лет всемирной истории, когда жило наибольшее количество выдающихся учёных. Выдающимися учёными редактор считает тех, кто упомянут в книге с датами их рождения и смерти. Ныне живущие учёные в книгу не включены.

Задание. Предложите редактору программируемый алгоритм решения задачи, если в качестве входных данных используется книжный указатель. Фамилии учёных в указателе отсортированы в алфавитном порядке, содержат годы рождения и смерти. Если человек А умер в том же году, в котором родился человек Б, считайте, что первое событие предшествовало второму.

Подсказка

Обратите внимание на последнее предложение задания. Зачем дано такое уточнение?

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

Когда будет ответ? Наши задачи не из простых. Чтобы все успевали решить задачу, и читатели не уставали от формата, мы решили делать головоломки не так часто. Задачи будут выходить в дни недели, начинающиеся на «c»: по средам и субботам. Ответ на задачу и новую головоломку опубликуем в субботу, в 14:00.

Идеи проекта выходного дня

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

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

Идеи. Не обязательно останавливаться на учёных. Вот несколько идей более специализированных проектов:

  • Карта русской литературы. Временна́я лента, по которой можно визуализировать когда жили разные русские писатели. Кто на кого мог влиять? Можно выбрать конкретный век. Такая идея была реализована в проекте Russian Writers CSV and some graphs (англ.). Есть от чего оттлокнуться, можно сделать по-своему.
  • Любите футбол? Можно использовать не годы жизни, а информацию о карьере футболистов, визуализировать переходы из клуба в клуб, участие в чемпионатах.
  • Играете в шахматы? Постройте ленту истории игры из годов первых упоминаний и названий каждого из именных видов дебютов, гамбитов, защит. В этом случае даты – одиночные точки, но и они расскажут о развитии шахмат.
  • Увлекаетесь фототехникой? Соберите инфографику с годами выпуска и автоматически собранными изображениями фотоаппаратов, покажите развитие отрасли.

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

Это лишь некоторые наводящие мысли. Ваши идеи мы будем рады увидеть в комментариях. Дерзайте!

***

Решение задачи о фамилии Тьюринга

Ответ: 598.

Решение. Фактически это комбинаторная задача на перестановки. Общее количество слов, составленное из шести букв, равно 6! = 6·5·4·3·2·1 = 720. Удобнее рассматривать те «слова», которые следуют после слова TURING. Потому что их меньше.

Такие слова имеют сначала вид TURN∗∗, потом сменяются словами вида U∗∗∗∗∗. Звёздочка обозначает одну из шести букв, которых ещё нет в слове. Для первой комбинации букв остаётся вариантов: 2!, для второй – 5!. То есть общее количество «слов», следующих за TURING равно 5! + 2! = 120 + 2 = 122.

Номер фамилии это число общих слов минус номер следующих за ней. Таким образом, если нумерация начинается с единицы, номер фамилии равен 720 – 122 = 598.

Программное решение 🌟🐍. Если вы не смогли решить задачу аналитически, можно было решить задачу программно. Ниже представлено простое решение на Python с использованием встроенной библиотеки itertools:

            from itertools import permutations


def find_surname_position(surname: str):
    surname = surname.upper()  # если фамилия написана не заглавными буквами
    letters = list(surname)  # список букв, из которых состоит фамилия
    letters_vars = permutations(sorted(letters), len(surname))  # перестановки
    words_vars = [''.join(item) for item in letters_vars]  # "слова" из букв
    position = words_vars.index(surname) + 1  # нумерация начинается с единицы
    return position

input_surname = input('Введите фамилию: ')

req = 'Номер фамилии в списке «слов», составленном из букв фамилии: {}.'
print(req.format(find_surname_position(input_surname)))
 
        
            Введите фамилию: TURING
Номер фамилии в списке «слов», составленном из букв фамилии: 598. 
        

Первыми решения головоломки дали пользователи NeizeR и rmg7. Поздравляем! Оба ответа правильные. Решение rmg7 в том же ключе, что и описанное нами, а ответ NeizeR наглядно показывает, почему подсчёт от начала списка оказывается дольше. Но и он приводит к правильному положению в списке.

Ниже мы процитировали ответы участников.

Перед первым словом на букву T будет 4×5! слов, поскольку есть 4 буквы перед T(G, I, N, R) и для каждой из них 5! способов переставить между собой 5 оставшихся букв. Дальше мы считаем сколько слов можна сделать из буквы T + букв которые идут перед U в списке оставшихся букв, то есть TG, TI, TN и TR(TT не включаем, потому что второй раз не можем ее использовать); количество таких перестановок будет равно 4×4! исходя из уже описанного алгоритма. Аналогично делаем для остальных комбинаций букв, которые будут находится перед словом TURING( TUG, TUI, TUN, TURG, TURIG). Сделав для этих комбинаций аналогические рассчеты, мы получим число 4×5! + 4×4! + 3×3! + 1×2! + 1×1! = 597. То есть перед словом TURING будет 597 слов, и, соотвественно, само слово TURING будет иметь номер 598.
быстрее будет решать в противоположном направлении Общее количество комбинаций 6!=720, 6!-5!(Uxxxxx)-0(TUxxxx)-0(TURxxx)-2!(TURNxx)-0(TURINx)=6!-5!-2!=720-120-2=598
15
Янв
2020

Как включить React в тему WordPress

От автора: начиная с WordPress 5.0, React (или его абстракция) теперь поставляется с WordPress. WordPress берет все библиотеки React и ReactDOM и экспортирует их в объект глобального окна с именем wp.element. Это немного отличается от того, как работает большинство приложений React. В обычном приложении React мы импортируем React, в WordPress — нет. Обычно с приложением […]

15
Янв
2020

Рейтинг языков программирования в 2020 году

Для оценки перспективности своих усилий каждый программист должен регулярно смотреть рейтинги языков программирования. Часто бывает так, что появится некоторый модный язык, о котором все начинают писать, но потом этот язык тихо исчезает.  Те программис…

14
Янв
2020

«Старое железо»: компьютер, который отказывается умирать — FACOM 128B

«Время жизни» технологий сократилось — смартфоны можно менять хоть каждый год. Но пока еще остается оборудование, которое работает на протяжении десятилетий. Одна из таких систем — японский компьютер FACOM 128B, введенный в эксплуатацию в 1…

14
Янв
2020

Специальное предложение для самых быстрых

Программирование — это целая вселенная. На данный момент в мире насчитывается несколько десятков действующих языков, на которых можно написать работающую программу. У каждого из них есть свои плюсы и минусы, но безусловным лидером является язык PHP. Ос…

14
Янв
2020

Задача о фамилии Тьюринга

Мы посвящаем следующую задачу Алану Тьюрингу (1912–1954) – английскому математику и криптографу, который, помимо других замечательных достижений, сыграл ведущую роль в развитии теоретической информатики.

Эт…

14
Янв
2020

Умеете ли вы правильно называть функции?

Как имя, которое хорошо описывает то, что делает функция, может на практике оказаться абсолютно бесполезным и что с этим делать? Рассказываем в статье.
— Читать дальше «Умеете ли вы правильно называть функции?»

13
Янв
2020

Python умер, да здравствует Python. Видеокурс по программированию на Python 3

Учимся программировать простые графические приложения на Python 3. Параллельно узнаём о Git и принципах качественного кода.
— Читать дальше «Python умер, да здравствует Python. Видеокурс по программированию на Python 3»

13
Янв
2020

21–22 января, онлайн: интенсив «Создание Telegram-бота для заказа кофе в заведении и оплаты онлайн»

В ходе интенсива участники научатся интегрировать сторонние платформы в Telegram, пользоваться системой уведомлений Laravel и создадут полноценного бота.
— Читать дальше «Интенсив «Создание Telegram-бота для заказа кофе в заведении и оплаты онлайн»»

13
Янв
2020

Задача об острове хамелеонов

История о меняющих цвет ящерицах и ответ на предыдущую задачу. Кто решит первым? Следим за комментариями на сайте.

Эта задача – третий эпизод нашего сериала головоломок. После описания задачи идёт ответ на …

12
Янв
2020

Задача о спрятанном решении

Головоломка в рамках нашего нового формата и ответ на предыдущую задачу. Догадаетесь, что школьник спрятал за звёздочками?

Эта задача является вторым эпизодом нашего сериала головоломок. После описания задачи представлен ответ на вчерашнюю задачу о двойных фамилиях.

Задача о спрятанном решении

Школьник перемножил два числа в столбик, а потом закрасил звездочками все цифры кроме одной девятки. Получилось как на картинке выше. Какие цифры стояли на месте звёздочек?

Ответ и решение – завтра в 14:00.

А сейчас? Пока что нужно попытаться самим. Идеи и решения можно обсудить в комментариях.

***

Решение задачи о двойных фамилиях

Математическое решение. Обозначим буквами: A, B, C, D «простые» фамилии внутри составных. Эти фамилии уже могут являться их общей фамилией.

Остальные фамилии – размещения из четырех по двум. Число размещений равно

4! / (4−2)! = 4! / 2! = 4 ⋅ 3 = 12.

Действительно, эти 12 вариантов можно и перебрать:

AB AC AD
BA BC BD
CA CB CD
DA DB DC

Таким образом, суммарное число фамилий равно шестнадцати.

Ответ: 16.

Программное решение 🌟🐍. Решим ещё и программно – на Python. Мы как раз недавно рассматривали применение библиотеки itertools. Попрактикуемся в применении:

            from itertools import chain, permutations


def find_all_surnames(surnames):
    # разбиваем составные фамилии по дефису
    surnames = [surname.split('-') for surname in surnames]
    
    # преобразуем в плоский список, получаем список "обычных" фамилий
    surnames = list(chain.from_iterable(surnames))
    
    # остальные варианты соответствуют перестановкам обычных фамилий
    perm_surnames = list(permutations(surnames, 2))
    
    # объединяем составные фамилии через дефис
    perm_surnames = ['{}-{}'.format(i, j) for (i, j) in perm_surnames]
    
    # соединяем два списка
    surnames.extend(perm_surnames)
    
    return surnames


# проверим работу функции на практике
surnames = find_all_surnames(['Склодовская-Кюри', 'Миклухо-Маклай'])

print('Общее число фамилий равно {}. Вот их список без учёта пола:'.format(len(surnames)))
for surname in surnames:
    print('- '+surname) 
        

Код выше выведет следующее:

            Общее число фамилий равно 16. Вот их список без учёта пола:
- Склодовская
- Кюри
- Миклухо
- Маклай
- Склодовская-Кюри
- Склодовская-Миклухо
- Склодовская-Маклай
- Кюри-Склодовская
- Кюри-Миклухо
- Кюри-Маклай
- Миклухо-Склодовская
- Миклухо-Кюри
- Миклухо-Маклай
- Маклай-Склодовская
- Маклай-Кюри
- Маклай-Миклухо 
        

Если вам понравилось решать задачу. Это решение использует две эффективные функции встроенной библиотеки itertools. Чтобы попрактиковаться в алгоритмах, решите ту же задачу, не задействовав библиотек. Сравните время выполнения кода.

12
Янв
2020

Иллюстрированное руководство по изменению формы массивов NumPy

Рассказываем, как перекраивать массивы NumPy в трех измерениях. Шпаргалка в конце руководства обобщает приемы работы с методами reshape, stack и ravel.

Трудность NumPy в том, что операции над многомерными массивами бывает сложно представить. Хаус Лин подготовил шпаргалки, которые сделают преобразование массивов нагляднее. Руководство подойдёт и для знакомства с NumPy.

1. Создаем массив NumPy

Аналог range для массивов. Чтобы создать простой массив, используем функцию np.arange(). Удобно взять небольшое составное число, например, 12.

            import numpy as np

a1 = np.arange(1, 13)  # числа от 1 до 12

print(a1.shape)
> (12,)

print(a1)
> [ 1  2  3  4  5  6  7  8  9 10 11 12] 
        
Создан одномерный массив из 12 чисел.

2. Изменяем форму с помощью метода reshape()

Оси и измерения. Чтобы изменить форму массива a1 , используем метод reshape(). Преобразуем одномерный массив из 12 чисел в двумерную таблицу размером 3×4. Первое число – количество строк, второе – столбцов. Строки соответствуют оси (англ. axis) 0, столбцы – оси 1. Ещё их называют измерениями (англ. dimensions).

            a1_2d = a1.reshape(3, 4)

print(a1_2d.shape)
> (3, 4)

print(a1_2d)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]] 
        

Автоматическое вычисление размерности. Если нужно, чтобы NumPy сам определил размер незаданного измерения, передайте на этой позиции значение -1:

            a1.reshape(3, 4)
a1.reshape(-1, 4)  # то же самое, что a1.reshape(3, 4)

a1.reshape(3, 4)
a1.reshape(3, -1)  # то же самое, что a1.reshape(3, 4)

a1.reshape(2, 6)
a1.reshape(2, -1)  # то же самое, что a1.reshape(2, 6) 
        

3. Изменяем форму по разным направлениям

Порядок переноса С. По умолчанию reshape() перестраивает исходный массив по оси 0. То есть в нашем примере отдельные числа из одномерного массива «переносятся» в двумерный построчно. Поведение можно изменить, передав значение параметру order. Дефолтный метод похож на то, как преобразование реализовано в C. Параметр order по умолчанию имеет значение 'C':

            a1.reshape(3, 4)
a1.reshape(3, 4, order='C') # даст идентичный результат
 
        

Порядок переноса Fortran. Если вы привыкли к тому, как преобразуются массивы в MATLAB, то это делается так же, как в Fortran. Поэтому используйте значение 'F':

            a1.reshape(3, 4, order='F')  # столбец за столбцом
> [[ 1  4  7 10]
   [ 2  5  8 11]
   [ 3  6  9 12]] 
        

Какую размерность имеет исходный массив a1? Может показаться, что массив a1 имеет размерность (1, 12). Но это одномерный массив с размерностью(12, ). Чтобы преобразовать одномерный массив к двумерному, используем метод reshape():

            print(a1)  # какая форма?
> [ 1  2  3  4  5  6  7  8  9 10 11 12]

print(a1.shape)
> (12,)

a1_1_by_12 = a1.reshape(1, -1)  # преобразуем к 1x12

print(a1_1_by_12)  # обратите внимание на двойные скобки
> [[ 1  2  3  4  5  6  7  8  9 10 11 12]]

print(a1_1_by_12.shape)  # двумерный массив
> (1, 12) 
        

4. Схлопываем массив до одномерного

Из 2D в 1D. Метод ravel() преобразует многомерные массивы в одномерные. Тот же параметр order определяет, «схлопнется» ли массив построчно или столбец за столбцом:

            print(a1_2d)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]

print(a1_2d.ravel())  # строка за строкой
> [ 1  2  3  4  5  6  7  8  9 10 11 12]

print(a1_2d.ravel(order='F'))  # столбец за столбцом
> [ 1  5  9  2  6 10  3  7 11  4  8 12] 
        

5. Повышаем размерность, сшивая массивы друг с другом


Создадим два массива:

            a1 = np.arange(1, 13)
print(a1)
> [ 1  2  3  4  5  6  7  8  9 10 11 12]

a2 = np.arange(13, 25)
print(a2)
> [13 14 15 16 17 18 19 20 21 22 23 24] 
        

Чтобы соединить два одномерных масива в двумерный, используем метод np.stack(). Параметр axis указывает индекс оси в результирующем массиве, по которой соединяются входные. По умолчанию axis = 0, и массивы стыкуются строка к строке:

            stack0 = np.stack((a1, a1, a2, a2))
print(stack0.shape)
> (4, 12)

print(stack0)
> [[ 1  2  3  4  5  6  7  8  9 10 11 12]
   [ 1  2  3  4  5  6  7  8  9 10 11 12]
   [13 14 15 16 17 18 19 20 21 22 23 24]
   [13 14 15 16 17 18 19 20 21 22 23 24]] 
        

Чтобы соединить массивы столбец к столбцу, явным образом передаем axis = 1:

            stack1 = np.stack((a1, a1, a2, a2), axis=1)
print(stack1.shape)
> (12, 4)
print(stack1)
> [[ 1  1 13 13]
   [ 2  2 14 14]
   [ 3  3 15 15]
   [ 4  4 16 16]
   [ 5  5 17 17]
   [ 6  6 18 18]
   [ 7  7 19 19]
   [ 8  8 20 20]
   [ 9  9 21 21]
   [10 10 22 22]
   [11 11 23 23]
   [12 12 24 24]] 
        

Как не повышать число измерений? Функция hstack() соединяет массивы горизонтально без изменения размерности. Если применить ее к одномерным массивам, получится длинный одномерный массив:

            stack_long = np.hstack((a1, a2))

print(stack_long.shape)
> (24,)

print(stack_long)
> [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24] 
        

6. Создаем трехмерный массив

Где применяются многомерные массивы? Массивы, живущие в трёх и более измерениях, активно используются в глубоком обучении. Например, для операций с изображениями. В работе с нейросетями преобразование многомерных массивов – обычное дело.

Для начала создадим два двумерных массива размером 3×4:

            a1 = np.arange(1, 13).reshape(3, -1)
a2 = np.arange(13, 25).reshape(3, -1)

print(a1)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]

print(a2)
> [[13 14 15 16]
   [17 18 19 20]
   [21 22 23 24]] 
        

Теперь соберём из них трёхмерный массив:

            a3_0 = np.stack((a1, a2))  # дефолтное axis=0, одна плоскость ложится на другую
a3_1 = np.stack((a1, a2), axis=1)
a3_2 = np.stack((a1, a2), axis=2)

print(a3_0.shape)
> (2, 3, 4)

print(a3_1.shape)
> (3, 2, 4)

print(a3_2.shape)
> (3, 4, 2) 
        

Как выглядят массивы:

            print(a3_0)
> [[[ 1  2  3  4]
    [ 5  6  7  8]
    [ 9 10 11 12]]

   [[13 14 15 16]
    [17 18 19 20]
    [21 22 23 24]]]

print(a3_1)
> [[[ 1  2  3  4]
    [13 14 15 16]]

   [[ 5  6  7  8]
    [17 18 19 20]]

   [[ 9 10 11 12]
    [21 22 23 24]]]

print(a3_2)
> [[[ 1 13]
    [ 2 14]
    [ 3 15]
    [ 4 16]]

   [[ 5 17]
    [ 6 18]
    [ 7 19]
    [ 8 20]]

   [[ 9 21]
    [10 22]
    [11 23]
    [12 24]]] 
        

Чтобы извлечь плоскость массива a1 из трехмерного, нужно передать 0 по соответствующему индексу оси:

            print(a1)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]

a3_0[0, :, :]
a3_1[:, 0, :]
a3_2[:, :, 0] 
        

Чтобы то же самое сделать для двумерного массива a2, на тех же позициях вместо 0 отправляем индекс 1. Символы двоеточия указывают, что нужно взять все элементы соответствующей оси.

7. Схлопываем многомерные массивы

Метод ravel() действует и для массивов с числом размерностей больше 2:


            print(a3_0)
> [[[ 1  2  3  4]
    [ 5  6  7  8]
    [ 9 10 11 12]]

   [[13 14 15 16]
    [17 18 19 20]
    [21 22 23 24]]]

print(a3_0.ravel())
> [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]

print(a3_0.ravel(order='F'))
> [ 1 13  5 17  9 21  2 14  6 18 10 22  3 15  7 19 11 23  4 16  8 20 12 24] 
        

8. Изменяем форму многомерных массивов

Метод reshape() также работает с массивами любой размерности. Главное условие, которое нужно соблюдать – количество элементов в массиве не должно меняться:

            print(a3_0)  # исходный размер 2x3x4
> [[[ 1  2  3  4]
    [ 5  6  7  8]
    [ 9 10 11 12]]

   [[13 14 15 16]
    [17 18 19 20]
    [21 22 23 24]]]

print(a3_0.reshape(4, -1))  # преобразуем к 4x6
> [[ 1  2  3  4  5  6]
   [ 7  8  9 10 11 12]
   [13 14 15 16 17 18]
   [19 20 21 22 23 24]]

print(a3_0.reshape(4, -1, order='F'))  # делаем то же самое, но в F-стиле
> [[ 1  9  6  3 11  8]
   [13 21 18 15 23 20]
   [ 5  2 10  7  4 12]
   [17 14 22 19 16 24]]

print(a3_0.reshape(4, 2, 3))  # преобразуем к трехмерному массиву другой формы
> [[[ 1  2  3]
    [ 4  5  6]]
   [[ 7  8  9]
    [10 11 12]]
   [[13 14 15]
    [16 17 18]]
   [[19 20 21]
    [22 23 24]]] 
        

Заключение

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


11
Янв
2020

Задача о двойных фамилиях

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

Новый формат. Каждый день в 14:00 будем публиковать в Библиот…

11
Янв
2020

6 идей проектов выходного дня

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

Кратчайшее расстояние между двумя точками – прямая. Скорейший способ освоить язык…

10
Янв
2020

Тезисно: 10 доводов, почему Java всё ещё хороший выбор для изучения нового языка

Десяток соображений, почему Java долго будет живее всех живых.

На рынке труда насчитывается свыше пятидесяти достойных внимания языков программирования. Немудрено, что от такого числа разбегаются глаза как …