for文・if文を用いて、条件を満たすパターンの組み合わせを出したい
43 ビュー (過去 30 日間)
古いコメントを表示
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 件のコメント
採用された回答
交感神経優位なあかべぇ
2022 年 12 月 16 日
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 件のコメント
交感神経優位なあかべぇ
2022 年 12 月 16 日
事前に計算できる個所は計算しておき、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 % 結果の表示
その他の回答 (1 件)
Hernia Baby
2022 年 12 月 16 日
まずはデータを用意
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 件のコメント
Hernia Baby
2022 年 12 月 16 日
存在しないのはそのような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回分テストを回すということなのでしょうか?
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!