for文・if文を用いて、条件を満たすパターンの組み合わせを出したい
43 views (last 30 days)
Show older comments
MATLAB初心者で手も足も出ないので、教えてください。
【やりたいこと】
条件を満たすような5つの変数のパターンの組み合わせを出したい。
任意の値:N=〇
変数:Za、Zb、Zc、Zd、Ze (全て整数で、値は5~150の範囲)
条件:Zc/Za>1
(Zb・Ze)/(Zc・Zd)>1
(Zb・Ze)/(Za・Zd)>1
X=(Za+Zc)/N (整数)
Y=(Za・Zd+Zb・Ze)/(N・(ZbとZdの最大公約数)) (整数)
Z=(Zc・ZdーZb・Ze)/(N・(ZbとZdの最大公約数)) (整数)
出力イメージとしては、
(Za、Zb、Zc、Zd、Ze)=(11、11、34、12、38)
(10、32、30、74、72)
・
・
・
よろしくお願いします。
2 Comments
Accepted Answer
交感神経優位なあかべぇ
on 16 Dec 2022
forとifを使って、素直に実装しようとすると、下記のようになりますかね。ただ、これだといつまで経っても処理が終わらないので、パフォーマンスを改善した実装が必要になると思います。
(ちなみにZ=(Zc・ZdーZb・Ze)/(N・(ZbとZdの最大公約数)) (整数)の条件のZcはZcでいいですかね?(コメントのコード文ではZcではなくZaだったので、どちらかが書き間違えかなと))
N = 5; % ピニオンの歯数
A = zeros(0, 5);
for Za = 5 : 150
for Zb = 5 : 150
for Zc = 5 : 150
for Zd = 5 : 150
for Ze = 5 : 150
if ~(Zc / Za > 1)
continue;
end
if ~((Zb * Ze) / (Zc * Zd) > 1)
continue;
end
if ~((Zb * Ze) / (Za * Zd) > 1)
continue;
end
X = (Za + Zc) / N;
if ~(X == floor(X))
continue;
end
Q = gcd(Zb, Zd);%ZbとZdの最大公約数
Y = (Za * Zd + Zb * Ze) / (N * Q);
if ~(Y == floor(Y))
continue;
end
Z = (Zc * Zd - Zb * Ze) / (N * Q);
if ~(Z == floor(Z))
continue;
end
A(end + 1, :) = [Za, Zb, Zc, Zd, Ze];
end
end
end
end
end
A % 結果の表示
上記コードの途中までの結果の答え
2 Comments
交感神経優位なあかべぇ
on 16 Dec 2022
事前に計算できる個所は計算しておき、for文内での計算はできるだけ最小限にするような形で実装しようとしましたが、答えが100万通りを超えていますので、中断しました。
N = 5; % ピニオンの歯数
A = zeros(1000000, 5);
prodList = (5 : 150)' .* (5 : 150);
ZxList = 5 : 150;
gcdList = zeros(146, 146);
for idx = 1 : 146
gcdList(idx, :) = gcd(ZxList(idx), 5 : 150);
end
prodQNList = gcdList .* N;
setAIdx = 1;
for ZaIdx = 1 : 146
for ZcIdx = ZaIdx + 1 : 146 % Zc/Za>1を満たすため、左式を使用。
X = (ZxList(ZaIdx) + ZxList(ZcIdx)) / N;
if ~(X == floor(X))
continue;
end
for ZbIdx = 1 : 146
for ZdIdx = 1 : 146
for ZeIdx = 1 : 146
if ~(prodList(ZbIdx, ZeIdx) > prodList(ZcIdx, ZdIdx))
continue;
end
if ~(prodList(ZbIdx, ZeIdx) > prodList(ZaIdx * ZdIdx))
continue;
end
prodQN = prodQNList(ZbIdx, ZdIdx); % ZbとZdの最大公約数
Y = (prodList(ZaIdx, ZdIdx) + prodList(ZbIdx, ZeIdx)) / prodQN;
if ~(Y == floor(Y))
continue;
end
Z = (prodList(ZcIdx, ZdIdx) - prodList(ZbIdx, ZeIdx)) / prodQN;
if ~(Z == floor(Z))
continue;
end
A(setAIdx, :) = [ZxList([ZaIdx, ZbIdx, ZcIdx, ZdIdx, ZeIdx])];
if setAIdx >= 1000000
error('変数Aの容量が足りません。');
end
setAIdx = setAIdx + 1;
end
end
end
end
end
A(setAIdx : end, :) = []; % 余ったデータの削除
A % 結果の表示
More Answers (1)
Hernia Baby
on 16 Dec 2022
まずはデータを用意
N = 1;
Z = randi([5 150],5000,5);
Za = Z(:,1);
Zb = Z(:,2);
Zc = Z(:,3);
Zd = Z(:,4);
Ze = Z(:,5);
条件を作る
idx1 = Zc./Za > 1;
idx2 = (Zb.*Ze)./(Zc.*Zd)>1;
idx3 = (Zb.*Ze)./(Za.*Zd)>1;
X = (Za+Zc)./N;
Y = (Za.*Zd+Zb.*Ze)./(N.*gcd(Zb,Zd));
Z = (Zc.*Zd-Zb.*Ze)./(N.*gcd(Zb,Zd));
% 整数か判定
idx4 = X == floor(X);
idx5 = Y == floor(Z);
idx6 = Z == floor(Z);
全てを満たす条件
idx = idx1 & idx2 & idx3 & idx4 & idx5 & idx6;
条件に合うものを抽出
Z(idx,:)
3 Comments
Hernia Baby
on 16 Dec 2022
存在しないのはそのようなZa,Zb,Zc,Zd,Zeがここには存在しないからです。
そして新しいコメントをみたのですが、ここでいう組み合わせとは
a = (1:3)';
b = (1:3)';
C = [a,b]
でいうと
for ii = 1:height(C)
a(ii)*b(ii) > 5
end
のように3回テストをまわすのではなく、
for ii = 1:length(a)
for jj = 1:length(b)
a(ii)*b(jj) > 5
end
end
のように3×3=9回分テストを回すということなのでしょうか?
See Also
Categories
Find more on Matrix Indexing 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!