中心を軸とした配列の入れ替え

24 views (last 30 days)
wataru suzuki
wataru suzuki on 22 Dec 2020
Commented: wataru suzuki on 24 Dec 2020
以下のような5×5の奇数列の配列Aを中心である3列目をそのままに
配列Bのように左右に入れ替えたいです。
しかしB=circshift(A,[0 5/2]); とすると
エラー: circshift
無効なシフト タイプ: 有限の実数の整数ベクトルでなければなりません。
と出てしまいます。fliperやfftshiftなどのコマンドをそのまま使ってもできなかったので
この場合どのように構文すべきか教えていただけないでしょうか?
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
B=
8 15 1 17 24
14 16 7 23 5
20 22 13 4 6
21 3 19 10 12
2 9 25 11 18

Accepted Answer

源樹 上林
源樹 上林 on 22 Dec 2020
 マニュアルを見ると circshift の2つ目の引数は整数と書いてあります。エラーメッセージに書いてあるとおりです。ceilとかfloorで整数にしたところで希望する結果は得られません。
 関数1個で解決するに越したことはないのですが、最適なものを見つけられなかったり、存在しなくて簡単には解決しないこともよくあります。そういうときは泥臭い方法で解決するのも一つの手段です。
まず2回にシフトしてみました。
A = magic(5)
hw = ceil(size(A,2)/2);
B = circshift(A, [0 hw]);
B(:,[1:hw]) = circshift(B(:,[1:hw]), [0 -1]);
B
これだと偶数配列の場合はだめですね。
配列のインデックスを使って入れ替え。
A = magic(5)
% 最終的にこのようにしたい
% B = A;
% B(:,[4 5 1 2]) = A(:,[1 2 4 5]);
w = size(A,2);
hw = floor(w/2);
i = circshift( 1:w, hw );
ib = i(1:hw*2)
ia = circshift( ib, hw );
B = A;
B(:,ib) = A(:,ia);
B
良さそうだけど、長しい、何をやっているのかがわかりにくい。
あわせ技を思いつきました。
A = magic(5)
B = A;
i = [1 2 4 5];
B(:,i) = circshift(A(:,i), [0 2]);
B
これならスッキリしてて動作も理解しやすそうです。iさえ作れれば。
w = size(A,2);
i = 1:w;
if mod(w,2)
i(ceil(w/2)) = [];
end
こうなるのか。結局あまりきれいには書けませんでしたが、これでご希望の変換ができると思います。
  2 Comments
Shunichi Kusano
Shunichi Kusano on 23 Dec 2020
上林さんの回答を見てすっきり書ける方法を思いついたので補足いたします。
A = magic(5)
i = [1 2 4 5]; % 5以外の場合、i = setdiff(1:size(A,2),ceil(size(A,2)/2));でOK
A(:,i) = A(:,circshift(i,2,2)); % 5以外の場合、シフト量は上と同様に変える
wataru suzuki
wataru suzuki on 24 Dec 2020
お二人ともありがとうございます。お蔭様でできそうです!

Sign in to comment.

More Answers (0)

Categories

Find more on ループと条件付きステートメント in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!