July 12th, 2017

green_fr

Pour la science (№ 476) — I

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


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

А в этом журнале статья о раскраске жемчужных ящериц:



У них каждая чешуйка своего цвета, раскраска по определению пиксельная. Учёные несколько лет сканировали ящериц, следя за изменением их раскраски. И в конце концов написали правила управляющего процессом клеточного автомата. И как здесь можно было не вспомнить программирование на Рыбе? А прочитав ТЗ к этому проекту, я внезапно понял, откуда растут ноги у нашего УБЗ :-)


Досье про тест Тьюринга в его современных версиях. Мне понравился вариант со схемой Винограда, когда роботу нужно разрешать неоднозначности естественного языка: «члены горсовета не дали положительного ответа демонстрантам, так как они боялись беспорядков во время манифестации». Человеку очевидно, кто имеется в виду под «они», а роботу нужно разбираться, выходя за рамки написанного, используя знания об окружающем нас мире.
(по-русски пример плохой, т.к. для демонстрантов можно было бы использовать «те» вместо «они», но я не смог с лёту придумать другой)


Статья о разрезании пиццы на одинаковые (по форме и площади) части. Рассматриваются вопросы вроде «можно ли разрезать так, чтобы какие-то части не касались середины пиццы?» (спойлер: можно).

Но начинается статья с того, как важно не попадать под влияние «очевидных» вещей. Например, говорит автор, очень долго считалось, что для того, чтобы вычислить какую-то цифру числа π, нужно сначала вычислить все предыдущие цифры этого числа. В принципе да, очевидно. Но неверно — в 1995 году нашли метод прямого вычисления любой цифры числа π, без вычисления предыдущих.

Читал про автора этого открытия: в 1977 году его занесли в книгу рекордов Гиннесса как человека, знавшего наизусть больше цифр числа π, чем кто-либо другой. Вообще-то он выучил первые 4400 цифр, но официальным представителям Гиннесса рассказал только 4096, потому что это круглое число. Наш человек.
green_fr

APL vs MatLab pII

Продолжаем фанфик курса программирования в УБЗ. catpad выкатил игру «Жизнь» одной строчкой на APL:



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

M = zeros(5);
M(3, 2 : 4) = 1;
V = {-1, 1};
B2 = cellfun(@circshift, repmat({M}, 1, 4), [V, V], 'UniformOutput', false);
B3 = cellfun(@circshift, B2, [V, fliplr(V)], repmat({2}, 1, 4), 'UniformOutput', false);
B4 = cellfun(@circshift, repmat({M}, 1, 2), V, 'UniformOutput', false);
B5 = cellfun(@circshift, repmat({M}, 1, 2), V, repmat({2}, 1, 2), 'UniformOutput', false);
B6 = sum(reshape(cell2mat(B3), [size(B3{1}), numel(B3)]), 3) + plus(B4{:}) + plus(B5{:});
B7 = B6 == 2;
B8 = B7 & M;
B9 = B6 == 3;
B10 = B8 | B9

Буковок несомненно больше. В первую очередь из-за параметра UniformOutput для cellfun: в MatLab «матрица, содержащая матрицу» — это cell array, и для него операции несколько отличаются от операций с матрицами.

Вторая неприятность заключается в том, что я не умею складывать элементы cell array. Для B4 и B5 всё просто — можно использовать sum, принимающий не более двух элементов, а там их как раз два. Но вот для B3 случается неприятность — я её обхожу переформатированием cell array -> matrix 5×20 -> matrix 5×5x4, которую затем суммирую вдоль третьего измерения. Если кто-нибудь подскажет более элегантный способ суммирования, я буду очень ему крайне признателен.

Сборка результата не отличается практически ничем. Отмечу отсутствие «;» в строке с B10, заставляющее MatLab вывести на экран результат этой операции. Лично я (равно как и встроенный анализ синтаксиса mlint) считаю это крайне порочной практикой и обычно использую для вывода на экран disp.

Теоретически это можно даже собрать в одну строчку, но здесь возникает ещё одна проблема — MatLab не позволяет написать (a + b)(:) (применить оператор индексации не к переменной, а к результату операции). Это обходится через subsref, который, впрочем, я тоже считаю плохой практикой.

Не говоря уже о засовывании всего этого в строку и вызове eval — от одного вида этой функции меня бросает в дрожь, она официально забанена у нас на проекте. Поэтому нет, циклы Жизни можно, конечно, запихнуть в одну длинную строку, но этим я не буду заниматься даже ради фанфика!