Поради щодо гольфу в MATLAB


14

Які загальні поради щодо гольфу в MATLAB? Я шукаю ідеї, які можна застосувати до коду проблем із гольфом взагалі, які принаймні дещо специфічні для MATLAB (наприклад, "видалити коментарі" - це не відповідь). Будь ласка, опублікуйте одну пораду на відповідь.


3

Відповіді:


10

Щось, що потрібно знати, перш ніж почати займатися гольфом:

У розрахунках MATLAB персонаж поводиться так само, як і його код ascii.

'abc' - 'a'  % Returns: [0 1 2]
'123' - '0'  % Returns: [1 2 3]
'“' == 8220  % Returns: 1 (logical)
'a':'e'==100 % Returns: [0 0 0 1 0] (logical)

9

Скорочення імен властивостей

У MATLAB рядки, що ідентифікують властивості, можуть бути скорочені до тих пір, поки це не призведе до неоднозначності.

plot(X,'C','k') % Ambiguous property found.
plot(X,'Co','k') % Expands to Color  (black)

Це насправді виграло мені виклик :)


2
Дуже добре, хоча відповідь правильна, я хочу підкреслити, що це стосується назви name, valueпар, як показано вище. (Тож не для таких речей sort(rand(4,1),'descend'))
Денніс Джахеруддін

1
Це стосується і деяких речей, як-от conv(1:5,[1 1],'s')замістьconv(1:5,[1 1],'same')
Луїс Мендо

6

Кастинг як char може бути виконаний шляхом об'єднання зі знаком:

x='a'+magic(5) % Array with character codes of several letters

char(x) % The standard way
['' x] % The compact way

Хоча це дозволяє заощадити лише один знак, його можна використовувати досить часто.


5

Рядки - це лише вектори рядків символів. Це означає, що замість

for i=numel(str)
    a=str(i)
    ...
end

можна просто написати

for(a=str)
    ...
end

Перший раз я використав це: /codegolf//a/58387/32352


4

Коріння єдності за допомогою дискретного перетворення Фур'є

Враховуючи додатне ціле число n, стандартним способом генерування n-го коренів єдності є

exp(2j*pi*(0:n-1)/n)

Це дає коріння починаючи з 1та рухаючись у позитивному кутовому напрямку. Якщо замовлення не має значення, це можна скоротити до

exp(2j*pi*(1:n)/n)

Оскільки exp(2j*pi/4)дорівнює уявної одиниці ( j), це можна записати більш компактно так (трюк через @flawr ):

j.^(4*(0:n-1)/n)

або

j.^(4*(1:n)/n)

Але дискретна трансформація Фур'є забезпечує ще коротший шлях (завдяки @flawr за видалення двох непотрібних дужок):

fft(1:n==n)

який дає коріння, починаючи з 1та рухаючись у позитивному кутовому напрямку; або

fft(1:n==2)

яка починається з 1і рухається в негативному кутовому напрямку.


Спробуйте все вищезазначене тут .


Чудова хитрість! Можна навіть fft(1:n==2)
пограти в

@flawr Я ніколи не знаю правил пріоритету ... Дякую!
Луїс Мендо

3

nnz іноді може заощадити кілька байт:

  • Уявіть, що ви хочете суму логічної матриці A. Замість sum(sum(A))або sum(A(:)), ви можете використовувати nnz(a)( nnzбезпримірно застосовується (:)).
  • Якщо ви хочете знати кількість елементів масиву, і ви можете бути впевнені, що немає нулів, замість цього numel(x)ви можете використовувати nnz(x). Це застосовно, наприклад, якщо xце рядок.

3

Ітерація над векторами в матрицях.

Враховуючи набір векторів як матрицю, ви можете насправді повторювати їх через єдиний для циклу, як

for v=M
    disp(v);
end

тоді як "традиційно" ви, мабуть, зробили б це так

for k=1:n
    disp(M(:,k));
end

Про цей трюк я дізнався лише зараз від @Suever у цьому виклику .


3

Пов’язані, але не ідентичні поради щодо Octave .

Маловідомою і мало використовуваною особливістю MATLAB і Octave є те, що більшість вбудованих функцій можна викликати без дужок, і в цьому випадку вони будуть розглядати все, що слідує за нею, як рядок (доки він не містить пробілів). Якщо він містить пробіли, вам потрібні лапки. Це часто можна використовувати для збереження байта при використанні disp:

disp('Hello, World!')
disp 'Hello, World!'

Інші, менш корисні приклади включають:

nnz PPCG
ans = 4

size PPCG
ans = 1  4

str2num 12
ans = 12

Я насправді використовував це двічі в розділі "Наскільки високо ви можете порахувати?" -виклик:

strchr sssssssssssssst t

еквівалентно strchr('sssssssssssssst','t')і повертається 15.

nnz nnnnnnnnnnnnnn

еквівалентно nnz('nnnnnnnnnnnnnn')і повертається 14.

Такі речі gt r sтеж працюють (еквівалентно 'r'>'s'або gt('r','s').


2

Вбудований onesі zeros, як правило, марно витрачає місце. Ви можете досягти того ж результату, просто помноживши масив / матрицю (потрібного розміру) на 0 (щоб отримати вихід zeros) та додати 1, якщо ви хочете вихід ones.

d = rand(5,2);

%// Using zeros
z = zeros(size(d));

%// Not using zeros
z = d*0;

%// Using ones
o = ones(size(d));

%// Not using ones
o = 1+d*0

Це також працює, якщо ви хочете створити вектор стовпця або рядка нулів або розмірів одного розміру матриці.

p = rand(5,2);

z = zeros(size(p,1), 1);
z = 0*p(:,1);

o = ones(size(p, 1), 1);
o = 1+0*p(:,1);

Якщо ви хочете створити матрицю певного розміру, яку ви можете використовувати, zerosале ви також можете просто призначити останній елемент 0 і мати MATLAB заповнити решту.

%// This
z = zeros(2,3);

%// vs. This
z(2,3) = 0;

2
Мені подобається використовувати ~(1:n)для нульових векторів 1-д.
sintax

2

2D ядра згортки

Це, можливо, ніша тема, але, мабуть, деякі люди люблять тут використовувати згортку для різних речей. [потрібна цитата]

У 2D часто потрібні такі ядра:

0 1 0
1 1 1
0 1 0

Цього можна досягти, використовуючи

v=[1,2,1];v'*v>1 %logical
v=[1,0,1];1-v'*v  %as numbers

яка коротша за

[0,1,0;1,1,1;0,1,0]

Ще одне ядро, яке часто використовується, це

0 1 0
1 0 1
0 1 0

які можна скоротити за допомогою

v=[1,-1,1];v'*v<0   % logical
[0,1,0;1,0,1;0,1,0] % naive verison

Друге ядро ​​як числа, кількість байтів:toeplitz([0 1 0])
Луїс Мендо

2

Я досить часто опиняюсь, що використовує meshgridабо ndgrid, скажімо, ми хочемо обчислити зображення мандельбрута, тоді ми ініціалізуємо, наприклад

[x,y]=meshgrid(-2:1e-2:1,-1:1e-2,1)

Тепер для набору манделброт нам потрібна ще одна матриця cрозміру xта, yале ініціалізована нулями. Це легко зробити, написавши:

c=x*0;

Ви також можете ініціалізувати його до іншого значення:

c=x*0+3;

Але ви можете фактично зберегти кілька байт, просто додавши інший вимір у meshgrid/ndgrid:

[x,y,c]=meshgrid(-2:1e-2:1,-1:1e_2,1, 0); %or for the value 3
[x,y,c]=meshgrid(-2:1e-2:1,-1:1e_2,1, 3);

І ви можете робити це так часто, як вам захочеться:

[x,y,c1,c2,c3,c4,c5]=meshgrid(-2:1e-2:1,-1:1e_2,1, 1,pi,exp(3),1e5,-3i)

Зауважте, що тим часом існує автоматичне мовлення: у багатьох випадках перший приклад можна замінити на x=-2:1d-2:1;y=x'.
недолік

0

Підсумовування послідовності функцій

  • Для підсумовування функцій f (x_n), де n - вектор послідовних цілих чисел, февал рекомендується, а не симсум.

    Syms x;symsum(f(x),x,1,n);
    Sum(feval(@(x)f(x),1:n));
    

    Зауважте, що елементарна операція .*і ./необхідна замість попарно двійкових операцій *і/

  • Якщо функцію можна наївно записати, не підходить ніхто з жодних останніх способів.

    наприклад, якщо функція є, logви можете просто виконати:, sum(log(1:n))яка представляє:

    Sum(f(1:n));
    

    для відносно складних функцій log(n)/x^n:

    Sum(log(1:n)./5.^(1:n))
    

    а ще коротше в деяких випадках, коли функція довша, як f(x)=e^x+sin(x)*log(x)/x….

    Sum(feval(@(y)e.^(y)+sin(y).*log(y)./y,1:n))
    

    що надзвичайно коротше, ніж sum(feval(@(y)e.^(1:n)+sin(1:n).*log(1:n)./(1:n),1:n))


Примітка. Цей трюк можна застосувати для інших операторів, що включають в себе, як prodабоmean


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.