質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

5回答

3935閲覧

数値の掛け算の組み合わせを知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2015/06/10 02:05

以下のように配列で、数値が与えられます。
$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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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

ngyuki

総合スコア4514

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ngyuki

2015/06/10 02:35

項が一つしかないものを除外するのであれば } else if ($val > 1) { を } else if ($cnt > 1) { とかにしてください。
退会済みユーザー

退会済みユーザー

2015/06/13 04:38

私にとって、一番理解しやすかったものを選ばせていただきました。 再帰処理以外での方法も、後学のために試してみようかと思います。 多くの回答ありがとうございました。
guest

0

実装方針だけを述べます。

  1. 0 か 1 を 10 個並べた組み合わせを順番に得ることができる stream をつくる。
  2. 得られた item (0,1 を要素とする 10 個の配列) に対して
    val = 1
    num = 0
    for i on [0..10]
    if item[i] != 0
    val *= prime_list[i]
    num ++
    として、掛け算の結果 (val)、掛け算につかった要素の個数 (num) を得ます。
  3. 上で得た val, num を 結果として蓄積します。
    蓄積方法としては、 キーを val, 値を num にした hash を使う。

(素数の掛け算なので、val には重複がない。
もし、素数のリストでなければ、掛け算結果に重複があり得えます。
その場合は hash の val は 配列にする)

すでに別の回答にあるように
1 の部分は strem でなく、 for でループを組んで 0 か 1 を 10 個並べた組み合わせを
得ることも可能です。

上の方法では、同じ掛け算を何回も行うことになります。
掛け算の実施回数を減らことを考えるなら、
使う要素の数が1つ増えたときは 過去の掛け算の結果に 増えた要素を1回 掛け算するようにする
という工夫をすることも可能です。

投稿2015/06/10 21:23

katoy

総合スコア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
ngyuki

総合スコア4514

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YukiMiyatake

2015/06/10 04:51

2進数と書いたつもりが ミスってましたすみません
guest

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
jun68ykt

総合スコア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

YukiMiyatake

総合スコア144

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問