以下のように配列で、数値が与えられます。
$prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
この中から組み合わせで掛け算した結果を取得したいです。
また、何個の数値の掛け算の結果かも取得したいです。
結果イメージとして
[ 15=>2, // 3*5 21=>2, // 3*7 ・・・(略)・・・ 105=>3, // 3*5*7 165=>3, // 3*5*11 ・・・(略)・・・ 1155=>4, // 3*5*7*11 ・・・(略)・・・ ]
(演算結果)=>(かけた数値の個数)
のような結果一覧を取得したいです
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
ベストアンサー
難しいことを考えずにサッと解くなら再帰すると簡単でしょうかね。
lang
1<?php 2$prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]; 3 4$result = []; 5 6function func(&$result, $list, $i = 0, $val = 1, $cnt = 0, $expr = "") 7{ 8 if ($i < count($list)) { 9 func($result, $list, $i+1, $val*$list[$i], $cnt+1, "$expr*{$list[$i]}"); 10 func($result, $list, $i+1, $val, $cnt, $expr); 11 } else if ($val > 1) { 12 $result[] = [$val, $cnt, trim($expr, '*')]; 13 } 14} 15 16func($result, $prime_list); 17//print_r($result); 18 19foreach ($result as list ($val, $cnt, $expr)) { 20 echo "$expr = $val ... ($cnt)\n"; 21}
最後の引数 $expr
は結果の確認のために設けているだけなので無くてもいいです。
投稿2015/06/10 02:32
総合スコア4514
0
実装方針だけを述べます。
- 0 か 1 を 10 個並べた組み合わせを順番に得ることができる stream をつくる。
- 得られた item (0,1 を要素とする 10 個の配列) に対して
val = 1
num = 0
for i on [0..10]
if item[i] != 0
val *= prime_list[i]
num ++
として、掛け算の結果 (val)、掛け算につかった要素の個数 (num) を得ます。 - 上で得た val, num を 結果として蓄積します。
蓄積方法としては、 キーを val, 値を num にした hash を使う。
(素数の掛け算なので、val には重複がない。
もし、素数のリストでなければ、掛け算結果に重複があり得えます。
その場合は hash の val は 配列にする)
すでに別の回答にあるように
1 の部分は strem でなく、 for でループを組んで 0 か 1 を 10 個並べた組み合わせを
得ることも可能です。
上の方法では、同じ掛け算を何回も行うことになります。
掛け算の実施回数を減らことを考えるなら、
使う要素の数が1つ増えたときは 過去の掛け算の結果に 増えた要素を1回 掛け算するようにする
という工夫をすることも可能です。
投稿2015/06/10 21:23
総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
2ビット数という事に注目すると 簡単に処理出来ると思います
2ビットというか各項を1ビットで表現する感じでしょうかね。
試しにやってみました。
lang
1<?php 2$prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]; 3$result = []; 4$max = 1 << count($prime_list); 5 6for ($i=0; $i<$max; $i++) { 7 $val = 1; 8 $cnt = 0; 9 $expr = ""; 10 for ($j=0,$k=$i; $k; $j++,$k=$k>>1) { 11 if ($k & 1) { 12 $val *= $prime_list[$j]; 13 $cnt++; 14 $expr = "$expr*{$prime_list[$j]}"; 15 } 16 } 17 if ($cnt > 1) { 18 $result[] = [$val, $cnt, trim($expr, '*')]; 19 } 20} 21 22foreach ($result as list ($val, $cnt, $expr)) { 23 echo "$expr = $val ... ($cnt)\n"; 24}
あるいは無駄に配列関数を駆使してみたり
lang
1<?php 2$prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]; 3$result = []; 4$max = 1 << count($prime_list); 5 6for ($i=0; $i<$max; $i++) { 7 $arr = array_filter(array_map( 8 function ($a, $b) { return $a * $b; }, 9 $prime_list, 10 preg_split("//", strrev(sprintf("%b", $i)), -1, PREG_SPLIT_NO_EMPTY) 11 )); 12 if (count($arr) > 1) { 13 $result[] = [array_product($arr), count($arr), implode("*", $arr)]; 14 } 15} 16 17foreach ($result as list ($val, $cnt, $expr)) { 18 echo "$expr = $val ... ($cnt)\n"; 19}
投稿2015/06/10 04:25
編集2015/06/10 04:45総合スコア4514
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
こんにちは。
問題の核になるのは
lang
1$prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
という配列を集合とみて、これの冪集合(power set)の要素をもれなく
生成するロジックをどう書くか?ということかと思いました。
なので、冪集合を作り出すロジックを調べるなどして、以下が出来ました。
lang
1<?php 2 3# --------------------------------------------- 4# 与えられた配列を集合とみなして、これの冪集合 5# に相当する配列を作成して返す。 6# --------------------------------------------- 7function beki($list) { 8 $result = []; 9 $n = count($list); 10 11 for ( $i =0; $i < (1<<$n); ++ $i ) { 12 $a = []; 13 for ( $j = 0; $j < $n; ++ $j ) { 14 if ( ($i >> $j) & 1 ) { 15 $a[] = $list[$j]; 16 } 17 } 18 $result[] = $a; 19 } 20 return $result; 21} 22 23# 与題の素数リスト 24$prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]; 25 26# べき集合に相当するリストを作成する。 27$power_list = beki($prime_list); 28 29# 与題に沿った出力をするための配列作成 30$results = array(); 31 32foreach ( $power_list as $list ) { 33 if ( count($list)==0 ) continue; 34 35 $product = 1; 36 foreach ( $list as $e ) 37 $product *= $e; 38 39 $results[$product] = count($list); 40} 41 42# 確認のための出力 43foreach( $results as $product => $count ) { 44 echo "$product => $count\n"; 45}
これを実行すると、以下のような出力を得ました。
3 => 1
5 => 1
15 => 2
7 => 1
21 => 2
・・・
2865149859 => 8
4775249765 => 8
14325749295 => 9
6685349671 => 8
20056049013 => 9
33426748355 => 9
100280245065 => 10
そして電卓で、3×5×・・・×29×31 を計算したら確かに
100280245065
となって出力の最終行と合っていて、正直ほっとしている次第です。
面白い問題、ありがとうございました。
投稿2015/06/10 03:09
編集2015/06/10 06:22総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
2 がリストに無いのが気になりますが・・
まず前提として、同じ素数は1回しか使われないですか?
例えば 3x3 はNG
私ならそうですね、この程度の数なら最初に 全パターンのリストを作ります
$prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
各素数は 10個ですので
2の10乗の組み合わせです。
全ての組み合わせに関してループし、array_push(演算結果,個数)
をすれば良いでしょう
全ての組み合わせは色々とやり方はありますが
愚直に10重ループにしても出来ますし
2ビット数という事に注目すると 簡単に処理出来ると思います
投稿2015/06/10 02:37
総合スコア144
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/06/10 02:35
退会済みユーザー
2015/06/13 04:38