APL vs MatLab pII
Jul. 12th, 2017 11:30 amПродолжаем фанфик курса программирования в УБЗ.
catpad выкатил игру «Жизнь» одной строчкой на APL:

Потратив некоторое время наподнятие челюсти восхищение чистым разумом, я задумался, как всё это выглядело бы на MatLab. На самом деле, отличия не сильные. Опять же, сохраняя обозначения исходного курса, разобьём на блоки:
Буковок несомненно больше. В первую очередь из-за параметра 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 — от одного вида этой функции меня бросает в дрожь, она официально забанена у нас на проекте. Поэтому нет, циклы Жизни можно, конечно, запихнуть в одну длинную строку, но этим я не буду заниматься даже ради фанфика!

Потратив некоторое время на
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 — от одного вида этой функции меня бросает в дрожь, она официально забанена у нас на проекте. Поэтому нет, циклы Жизни можно, конечно, запихнуть в одну длинную строку, но этим я не буду заниматься даже ради фанфика!
no subject
Date: 2017-07-12 10:54 am (UTC)На специализированном языке "Жизнь" программа была бы еще короче.
no subject
Date: 2017-07-12 10:59 am (UTC)Насчёт специализированного языка. Можно, конечно, создать специальный язык, в котором будет встроенная функция Life(M, N), которая печатает N поколений исходной матрицы M. Это будет самая короткая реализация Жизни на свете!
no subject
Date: 2017-07-12 11:05 am (UTC)no subject
Date: 2017-07-12 11:37 am (UTC)no subject
Date: 2017-07-13 09:04 pm (UTC)no subject
Date: 2017-07-13 10:24 pm (UTC)