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

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

新規登録して質問してみよう
ただいま回答率
85.47%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

12回答

2166閲覧

1から100までの数字をそれぞれ1つずつを100個使って、偶数もしくは奇数が4回以上続かないように並べる(配列を作る)アルゴリズム

shihatu

総合スコア2

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

2クリップ

投稿2022/01/17 00:37

タイトルにもあるとおり、
1から100までの数字をそれぞれ1つずつを100個使って、偶数もしくは奇数が4回以上続かないように並べる(配列を作る)アルゴリズムを教えていただきたいです。
例えば
x = [99,1,4,5,2,66,45...]
length(x)
→100
のようなものを作成したいです。
条件にもあるとおり、よくないパターンは
1, 偶数が4回以上続いている(奇数も同様)
x = [77,2,4,3,66,88,42,72]
2, 同じ数値がある(下の例では99)
x = [99,1,4,5,2,66,99...]

同じ数値を使わずに1から100までの数値を使ってランダムな配列を作成することは、組み込み関数(MATLAB)を使ってできますが、良くないパターン1の条件を満たせません。
自分がわかる言語はpythonとmatlabですので、そちらの言語で教えていただくのがベストですが、難しい場合は、言葉で説明していただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

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

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

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

maisumakun

2022/01/17 00:52

条件を満たすものは均等な確率で出す必要がありますか?
shihatu

2022/01/17 01:04

均等な確率で出す必要があります
fana

2022/01/17 03:03

teratailの状況がガタガタだからといって,マルチポストして良いということにはならない.
guest

回答12

0

普通にランダムに取り出しながら配列を埋めていき、連続が 4 になった場合は選び直しをするというので良いと思います。
選び直しは、出せる数が偶数か奇数か決まっているので、その中から選びます。

出た偶数の数が極端に多くなった場合、残りは奇数が多いので奇数が出る確率が高くなり、逆もまた然りなので、自動的にバランスが取れるでしょう。

偶数奇数のどちらかの残りがもう片方の 1/4 未満になった場合は破綻しますが、最終局面以外ではそこまで極端な偏りは生まれないと思います。1/4 になった時点で偶奇の配置が決まるので、そこからは偶数を出すか奇数を出すか決めてから取り出すアルゴリズムに変わります。

例えば、偶数 2 個、奇数 8 個が残った場合、それまでで最後に出た数が偶数であれば、奇奇奇偶奇奇奇偶の配置になり、最後に出た数が奇数であれば、偶奇奇奇偶奇奇奇になります。

正確に言えば、最後の奇奇奇偶については、最初が奇数であれば後の並びはランダムで問題ありません。

追記
1/4 は 1/3 の誤りです。

投稿2022/01/17 02:23

編集2022/01/17 02:55
Zuishin

総合スコア28660

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

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

Zuishin

2022/01/17 06:30

teratail のアクティブタブのテストも兼ねてコメントします。 > 普通にランダムに取り出しながら配列を埋めていき、連続が 4 になった場合は選び直しをするというので良いと思います。 連続が 3 になった時点で次に出す奇数・偶数を決めれば選びなおしの必要はありませんね。
Zuishin

2022/01/17 06:31

回答へのコメントの追加ではアクティブになりません。
guest

0

いちばん手抜きな方法としては、「何も考えずにシャッフルして、条件を満たさなければもう一度」を繰り返す方法が考えられます。

投稿2022/01/17 00:51

maisumakun

総合スコア145186

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

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

shihatu

2022/01/17 01:09

条件を満たさなければもう一度はかなり処理時間を必要としそうな気がします。判定の方法はわかりますが、並び替えるアルゴリズムの方法を教えていただけると幸いです。
maisumakun

2022/01/17 01:36 編集

厳密に均等になるかはわかりませんが、こんな方法を考えてみました。 ・先頭が偶数か奇数かを半々の確率で選ぶ ・先頭に、偶奇が同じものがものがいくつ続くかを、1つになるのが4/7、2つが2/7、3つが1/7の確率になるように決める ・次のも同じように1つか2つか3つかを選ぶ ・片方が50個以上になるまでこれを続ける ・最後に取ったもので50個を超えてしまった、あるいは片方が50個に達した段階でもう一方が4つ以上残っていた場合はやり直し ・偶奇のパターンが決まったところで、偶数だけ・奇数だけでシャッフルして数を詰める こうすれば、やり直しの可能性はだいぶ小さくできそうです。
shihatu

2022/01/17 01:55

理解不足ですみません。'先頭'というのは結果出力(求めている配列)の最初に置くということでしょうか '次のも'というのは例えば偶数が続いていた時に奇数に変わった時、次も奇数が続く確率のことをさしていますか
maisumakun

2022/01/17 02:23

はい、どちらもそのとおりです。
guest

0

題意をみたす列を全パターン出せそうな方法(途中,考察をダラダラと記述)

Step1: 1以上100以下の奇数を Fisher-Yates shuffle しておきます.

MATLABなら fy = randperm(100); のあと fyodd=fy(mod(fy,2)==1); など.
また,python なら import random から
fyodd=list(range(1,101,2)) をして random.shuffle(fyodd) など.
random.shuffle() はfyoddの中身を直接書きかえてしまうのですね.

Step2: 同様に,1以上100以下の偶数を Fisher-Yates shuffle しておきます.

次に,偶奇の切り替わり回数は最多で99回,最少で33回です.
(切り替わりが最少となる例) 奇奇奇,偶偶偶, ... ,奇奇奇,偶偶偶,奇奇,偶偶(カンマが33個)

連続する{奇数/偶数}のかたまりを「1かたまり」と数えると,
かたまりの個数の最大値は100,最小値は34です.
また,減らせるかたまりの個数=減らせる偶奇の切り替わりの回数 です.
これをmとおくと,0<=m<=66 となります.

Step3: 0以上66以下の整数mをランダムに決定します.

題意を満たす列における{奇数/偶数}のかたまりの数の最大値は各50,最小値は各17です.
{奇数/偶数}のかたまりの個数をそれぞれ{mo回/me回}減らすことにして,
0<=mo<=33 かつ 0<=me<=33 かつ abs(mo-me)<=1 となるように mo, me を決定します.

Step4: mが偶数の場合,mo=me=m/2とします.また,mが奇数の場合,moとmeのうち片方を(m+1)/2,もう片方を(m-1)/2とします.

奇数のかたまりの個数を減らしていきます.
かたまりの個数を1つ減らすごとに,いずれか1つのかたまりのサイズが大きくなります(増えるサイズは後述).

Step5: 1以上49以下の数をmo個並べてできる列 {ro_1, ro_2, ... , ro_mo}を考えます.また,もしmoの値が0ならばStep8に移ります.
Step6: 次に「奇,奇, ... ,奇」という(かたまりサイズ1の奇数50個をカンマで区切った)並びを考えます.
Step7: i = 1, 2, ... ,mo に対して以下を行います:「もし,Step6の時点で左から ro_i番目の位置にあったカンマを取り除いても,奇数が4つ以上連続しないならば,そのカンマを取り除く(これにより,取り除くカンマの左にあったかたまりのサイズが「取り除くカンマの両脇にあった2つのかたまりのサイズの和」となる)」

同様に,偶数のかたまりの個数を減らしていきます.

Step8: 1以上49以下の数をme個並べてできる列 {re_1, re_2, ... , re_me}を考えます.また,もしmeの値が0ならばStep11に移ります.
Step9: 次に「偶,偶, ... ,偶」という(かたまりサイズ1の偶数50個をカンマで区切った)並びを考えます.
Step10: i = 1, 2, ... ,me に対して以下を行います:「もし,Step6の時点で左から re_i番目の位置にあったカンマを取り除いても,偶数が4つ以上連続しないならば,そのカンマを取り除く(これにより,取り除くカンマの左にあったかたまりのサイズが「取り除くカンマの両脇にあった2つのかたまりのサイズの和」となる)」

以上の操作によって生成された最大サイズ3の偶奇のかたまりを並べていきます.

Step11: もし mo-me=1 ならば,奇数のかたまりから開始して,以下{奇数/偶数}のかたまりを交互に置いていく.また,もし me-mo=1 ならば,偶数のかたまりから開始して{奇数/偶数}のかたまりを交互に置いていく.いずれにも該当しなければ,me=moなので,{奇数/偶数}どちらのかたまりから開始しても良いが,以下{奇数/偶数}のかたまりを交互に置いていく.

その結果,mo-me=1 の場合が奇数のかたまりで終わり,me-mo=1 の場合は偶数のかたまりで終わります.
また,me=mo で奇数のかたまりから開始した場合は偶数で,偶数のかたまりから開始した場合は奇数で,それぞれ終わります.

題意をみたす列は,必ずこの手法で表現し得るのではないかと思っています.
ただし,出方が一様かどうかの検証はしていません.

投稿2022/01/28 04:11

編集2022/01/28 08:43
obeSolitary

総合スコア106

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

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

0

奇数50個、偶数50個に分ける
それぞれを任意の順番に並び替える
偶奇偶奇…偶奇(またはその逆)の順に並べる
「3つ以下ずつ」、の組み合わせにする(下記参照)
(偶奇偶)(奇偶)(奇)(偶奇偶)(奇偶奇)…(偶)(奇偶奇)
()内を任意の順番に並び替える

完全な等確率ではないですが、結構簡単に実装できますよ。

投稿2022/01/18 00:23

編集2022/01/18 09:31
majiponi

総合スコア1720

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

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

maisumakun

2022/01/18 00:42

この方法だと、6つで奇偶の個数が一致してしまうので、奇奇奇偶奇奇奇偶奇偶偶偶奇偶偶偶のようなパターンが出ないですね。
majiponi

2022/01/18 09:30

そう、なんですが、3つ以下づつ、に変えれば問題なさそうですね。
obeSolitary

2022/01/28 05:57 編集

横から失礼いたします. 「偶奇偶奇…偶奇(またはその逆)の順」からスタートした場合, 「3つ以下ずつ」であっても「先頭から」奇奇奇のパターンを出せないように思われ,ご教示ください. 奇偶奇偶奇偶... からスタートして,(奇偶)奇偶奇偶... でも (奇偶奇)偶奇偶... でも, その後のいかなる並べ替えに対しても先頭から3つを奇奇奇とすることができず, 最初の組について (奇)偶奇偶奇偶... とするよりありません.しかし, (奇)(偶)奇偶奇偶... 2番目が偶になってしまう (奇)(偶奇)偶奇偶... 2番目,3番目のいずれかが偶になってしまう (奇)(偶奇偶)奇偶... 2番目,3番目のいずれかが偶になってしまう 以上より,先頭から3つを奇奇奇とすることができないように思われます.
majiponi

2022/01/28 10:51

あー、なるほど。なら、先頭にダミーの奇数を置いて、並べ替えた後で先頭を削除、偶数を削除したらどこかの連続する奇数から1つ奇数を削除、連続する奇数がなければどれかの奇数を消す、というのはいかがでしょうか?
obeSolitary

2022/01/30 01:48 編集

返信ありがとうございます.即答できず,色々試しておりました. 最初の並びで奇数が2個以上出てきたら(奇奇奇...,奇奇偶...,奇偶奇...,偶奇奇...), その後「3つ以下ずつ」のどのような組み分け,その後の各組に対するどのような並べ替えに対しても 先頭から3つを偶偶偶のパターンにはできないように思います. 偶奇逆の場合も同様のことが言えます. つまり,最初にどのような並びを選んでも全パターンは出せないのではないでしょうか.
majiponi

2022/01/30 10:55

うむ、全部のパターンは無理だと思う。それを承知で、それらしく見えるものを簡単に実装できるものを書いてたってのは事実。
guest

0

18~49の整数をランダムに選ぶ。この数字をnとする
(16~50の整数でもいいですが、説明が複雑になるので端折ります)
-1~1の整数をランダムに選ぶ。この数字をkとし、m=n+kとする
1~100を偶数、奇数に分けてそれぞれの山をシャッフルする
要素数1のグループをn個、奇数の山から作る
できたグループに1~nの番号をつける
そして1~nの整数をランダムに生成し、出た数の番号のグループに奇数の山から1つ配る
(ただし、要素数が3のグループには配らない)
これを奇数の山がなくなるまで繰り返す
次に、要素数1のグループをm個、偶数の山から作る
できたグループに1~mの番号をつける
そして1~mの整数をランダムに生成し、出た数の番号のグループに偶数の山から1つ配る
(ただし、要素数が3のグループには配らない)
これを偶数の山がなくなるまで繰り返す
あとは、
k=-1の時は奇数のグループから始めて交互にグループを並べる
k=1の時は偶数のグループから始めて交互にグループを並べる
k=0の時はどちらが先でもいいので交互にグループを並べる

投稿2022/01/17 22:05

編集2022/01/17 23:06
modieu

総合スコア282

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

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

fana

2022/01/18 01:57

端折られた部分を含めるとしたら, nの範囲を 17~50 として,kの値を ・n=17のとき,kは 0 or 1 ・n=50のとき,kは -1 or 0 ・それ以外のとき,k = -1,0,1 のいずれか とすれば良いのかな. --- 確率を均等にするには,n(kも?)の各値の出現率を相応に(その先のパターン数に応じた形に)定めないとならない感.
guest

0

偶数,奇数を別の配列に分けて,それぞれをランダムシャッフルしておく

偶数,奇数のどちらかの配列から要素を持ってきては,現在の結果数列の挿入可能な位置のいずれかに挿入する
(もしも挿入可能な位置が無い場合は別の側の配列から要素を持ってきて処理することとする)

というだけで良いのでは.

(結果数列を線形リストとして考えて,ルール的に挿入可能な位置の中から挿入位置をランダムで選ぶだけの話)

投稿2022/01/17 03:59

編集2022/01/17 04:05
fana

総合スコア11660

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

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

fana

2022/01/17 04:02

偶奇2つの配列に分けずとも,単に「現在の数列に挿入不可能な値は配列の末尾あたりに戻すことで後回しにする」とかでも良いのかもしれないが.
fana

2022/01/17 04:04

単に「ルールを破らない位置に追加していけばいい」っていう. いろいろごちゃごちゃと考えずとも,これだけで済む話にも思えるのだが,どうなんでしょう?
guest

0

偶数50個奇数50個の並びで4個以上連続しない並びを決めれば、あとはそれに偶数の順列と奇数の順列を等しい確率で割り当てればいいだけなので、問題は偶数50個と奇数50個の4個以上連続しない並びを求めるところだけです。

この下長々と書いてますがおそらく相当わかりづらいのでさわりだけ言えば、パターン数を求めてパターン数の比率に応じて選ぶことを繰り返せば全パターンを等確率で選んだり、全パターンを列挙することができます。


d(len, evenCount, prev2, prev1, prev0) を長さ(len >= 3)でそのうち偶数をevenCount個使った並びで、末尾から2文字目、1文字目、0文字目の偶奇性がprev2, prev1, prev0で表せるようなもののパターン数とすると

len == 3 のとき、prev2, prev1, prev0のうち、偶数であるようなものの個数がevenCount個であるものは 1 、そうでなければ 0 len > 3 のとき、 evenCount not in [0, len] ならば 0 そうでないとき if prev0 is even then//最後が偶数 if prev1 is even && prev2 is even then//末尾3文字がすべて偶数 => 4文字前は奇数でなければならない d(len - 1, evenCount - 1, odd, prev2, prev1) else//そうでないなら偶数でも奇数でもいい d(len - 1, evenCount - 1, even, prev2, prev1) + d(len - 1, evenCount - 1, odd, prev2, prev1) else//最後が奇数の場合略 if prev1 is odd && prev2 is odd then d(len - 1, evenCount, even, prev2, prev1) else d(len - 1, evenCount, even, prev2, prev1) + d(len - 1, evenCount, odd, prev2, prev1)

となります。

これが分かればあとは、構築する関数s(len, evenCount, prev2, prev1, prev0)を同様に

len == 3 のとき、prev2 + prev1 + prev0 len > 3 のとき、 if prev0 is even then if prev1 is even && prev2 is even then s(len - 1, evenCount - 1, odd, prev2, prev1) + even else which = random from [0, d(len, evenCount, prev2, prev1, prev0)) if which < d(len - 1, evenCount - 1, even, prev2, prev1) then s(len - 1, evenCount - 1, even, prev2, prev1) + even else s(len - 1, evenCount - 1, odd, prev2, prev1) + even else//以下略

とでき、最終的にほしい列としては

allPattern = sum of d(100, 50, prev2, prev1, prev0) forall (prev2, prev1, prev0) which = random from [0, allPattern) pattern = 0 for prev2 in (even, odd) for prev1 in (even, odd) for prev0 in (even, odd) pattern += d(100, 50, prev2, prev1, prev0) if witch < pattern then return s(100, 50, prev2, prev1, prev0)

という感じで求められます。

投稿2022/01/17 03:04

yudedako67

総合スコア2047

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

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

0

3連続奇数or偶数が続いた場合は別のグループから選択するプログラムを実装しました。
配列数、奇数、偶数それぞれの最大連続数を設定できる形です。
条件に沿う形で出来る限りランダム性を担保していると思います。

尚、条件に合う数列が生成できないケースでは、一から再計算します。

また、その失敗する確率も計算させましたが、
n=100, max_odd_sequense=3, max_even_sequense=3の条件では、11%程度でした。

python

1import random 2import numpy as np 3 4def make_conditional_sequence(n=100, max_odd_sequense=3, max_even_sequense=3, failed=0): 5 choice_list = list(range(n)) 6 random_array = [] 7 #print('Start') 8 for i in range(n): 9 before_odd_array = random_array[-max_odd_sequense:] 10 before_even_array = random_array[-max_even_sequense:] 11 is_odd = [True if i%2 !=0 else False for i in before_odd_array] 12 is_even =[True if i%2 ==0 else False for i in before_even_array] 13 14 if sum(is_odd) >= max_odd_sequense: 15 even_list = [i for i in choice_list if i%2 == 0] 16 if len(even_list) == 0: 17 #print('this trial failed') 18 return make_conditional_sequence(n, max_odd_sequense, max_even_sequense, failed=failed+1) 19 else: 20 choiced = random.choice(even_list) 21 #print('random choiced from even', choiced) 22 23 24 elif sum(is_even) >= max_even_sequense: 25 odd_list = [i for i in choice_list if i%2 != 0] 26 if len(odd_list) == 0: 27 return make_conditional_sequence(n, max_odd_sequense, max_even_sequense, failed=failed+1) 28 else: 29 choiced = random.choice(odd_list) 30 31 else: 32 choiced = random.choice(choice_list) 33 34 choice_list.remove(choiced) 35 random_array.append(choiced) 36 37 #print(f'failed {failed}') 38 39 return random_array, failed 40 41failed_list = [] 42for i in range(100): 43 random_ , failed = make_conditional_sequence(n=100, max_odd_sequense=3, max_even_sequense=3) 44 #print(random_) 45 failed_list.append(failed) 46 47 48print(failed_list) 49p = sum(failed_list) / sum([i+1 for i in failed_list]) 50print(p)

投稿2022/01/17 02:59

編集2022/01/17 10:11
horiegom

総合スコア152

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

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

0

連続で出てくる数字の回数が均等になってしまいますが
偶数と奇数のグループに分けて
3回連続で出てくる偶数(奇数)を8グループ
2回連続で出てくる偶数(奇数)を8グループ
1回連続で出てくる偶数(奇数)を10グループ
作成してそれを偶数奇数交互に配置していけば要件を満たすのではないでしょうか?
この場合、偏った偶奇が50回繰り返すパターンなどは生成されませんが

投稿2022/01/17 02:59

gogoweb_ikeda

総合スコア1426

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

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

0

100個の数値を,数値4個からなるグループに分けることを考える.(25個のグループになる)

以下を12回繰り返すことでグループを24個作り出す.

  • 新しいグループに含める偶数の個数Nを{1,2,3}から乱数で決める.

 まだいずれのグループにも振り分けられていない数値群からてきとーに{偶数をN個,奇数を4-N個}もってきてグループを作る.

  • このとき,もうひとつのグループを{偶数を4-N個,奇数をN個}という分配で同様に作る.

残った数値4個を最後の(25個目の)グループにする.
これで25個のグループができた.

これらのグループを連結していくことで結果の数列(100個の数値の並び)を作ることを考える.

  • 数列は最初は空である.
  • 「いずれかのグループを選択しては数列の末尾に追加する」を25回繰り返すことで数列を完成させる.
  • あるグループを数列末尾に追加する際,このグループ内の4個の数値の並びは,数列に追加してもOKなパターン(追加結果が偶数or奇数4連以上の並びを作らないパターン)からランダムで決める.

といった感じで.

投稿2022/01/17 02:30

fana

総合スコア11660

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

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

fana

2022/01/17 02:38

グループを作る処理での「てきとーに{偶数をN個,奇数を4-N個}もってきて」の部分は,他の回答に書かれているように,偶数と奇数を別々に事前シャッフルしておいてそこから順次取り出していけば良いかな.
fana

2022/01/17 02:49

この手続きなら,とりあえず「途中で条件を満たせなくなる」ことは無いのではないかと思う. 出ないパターンがあるか否か? 出現率は均等か? 等に関しては私には不明.(頭良い人の判定に期待^^)
guest

0

均等な確率になるかは分かりませんが、 以下のような処理で条件を満たす配列は得られそうです。
ただし以下の処理では、条件は満たすが出現しないパターンがあるようです。

Python

1# 1から100までの数字を奇数と偶数それぞれ別の配列に入れて要素をシャッフルする。 2 3# 以下、2つの配列のどちらも空になるまでループ 4 5 # 奇数、偶数どちらの配列から値を採るかを以下のルールで決定する。 6 # 7 # - 2つの配列の個数の差が3個以上なら多いほうを採る。 8 # 「連続した値」が3回以上なら、反対のほうを採る。 9 # - いずれかの配列が空なら、まだ残っているほうを採る。 10 # - それ以外なら奇数または偶数いずれかをランダムに採る。 11 12 # 採るほうの配列先頭から値を抜き取り結果配列に追加する。 13 # 採るほうが変わったら「連続した値」を1回にクリアする。

投稿2022/01/17 01:15

編集2022/01/17 01:59
can110

総合スコア38266

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

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

maisumakun

2022/01/17 01:21

前半に「偶数3つ奇数1つ」が続いて、後半で「奇数1つ偶数3つ」が続いて帳尻を合わせるなど、これでは出ないパターンがありますね。
shihatu

2022/01/17 01:38 編集

確かにそうですね。今考えてるのは一度100個ランダムに並べてみて、配列の前から3つずつのグループに分けてsumして剰余を考え、その並びで法則がないか考えていますが、いまいちいいのが浮かびません
can110

2022/01/17 01:39

ご指摘ありがとうございます。 具体的なパターンは思いつきませんが「出ないパターン」が存在するということは均等な確率ではないですね。
can110

2022/01/17 02:01

条件を満たさない(4連続以上する)場合があったので 「これまで連続した値(回数)」もチェックするように処理を修正しました。
guest

0

続かなければいいだけなら奇数、偶数、奇数、偶数、・・・・
の順で処理すればいいでしょう。
偶数と奇数をそれぞれ配列に抽出してシャッフルして順番に抜き出す感じです。
4つ以上続かないという条件をつけた時点ですでにランダム性は損なわれています

sample

ロジックの質問なのでjsでサンプル提示します

javascript

1<div id="view" style="word-break:break-all;"></div> 2<script> 3const num=50; 4const cnt=3; 5const chusen=(num,cnt,len=null)=>{ 6 let tmp_i; 7 let tmp_num; 8 let counta=0; 9 const ret={}; 10 const retry=1000; 11 do{ 12 tmp_num=num; 13 ret.len=0; 14 ret.retry=0; 15 for(let i=cnt;i>=1;i--){ 16 tmp_i=(i>1)?parseInt(Math.random()*parseInt(tmp_num/i)):tmp_num; 17 ret[i]=tmp_i; 18 ret.len+=tmp_i; 19 tmp_num-=tmp_i*i; 20 } 21 if(counta++>=retry) return null; 22 ret['retry']=counta; 23 24 }while(len!=null && ![0,1].includes(len - ret.len)); 25 return ret; 26}; 27const res=[]; 28const list={ 29 odd:Array(num).fill(null).map((_,x)=>[x*2+1,Math.random()]).sort((x,y)=>x[1]-y[1]).map(x=>x[0]), 30 even:Array(num).fill(null).map((_,x)=>[x*2+2,Math.random()]).sort((x,y)=>x[1]-y[1]).map(x=>x[0]), 31}; 32const c1=chusen(num,cnt); 33console.log(c1); 34const c2=Array(cnt).fill(null).map((_,x)=>Array(c1[x+1]).fill(x+1)).flat().map(x=>[x,Math.random()]).sort((x,y)=>x[1]-y[1]).map(x=>x[0]); 35console.log(c2); 36const c3=chusen(num,cnt,c1.len); 37console.log(c3); 38const c4=Array(cnt).fill(null).map((_,x)=>Array(c3[x+1]).fill(x+1)).flat().map(x=>[x,Math.random()]).sort((x,y)=>x[1]-y[1]).map(x=>x[0]); 39console.log(c4); 40 41let choice=Math.random()<0.5?"odd":"even"; 42for(var i=0;i<c2.length;i++){ 43 [c2,c4].forEach(x=>{ 44 if(tmp=list[choice].splice(0,x[i])) res.push(tmp); 45 choice=choice=="odd"?"even":"odd"; 46 }); 47} 48view.textContent=res.flat().join(','); 49</script>

調整しました

投稿2022/01/17 00:44

編集2022/01/17 05:53
yambejp

総合スコア114863

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

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

shihatu

2022/01/17 01:07

回答ありがとうございます。 奇数を1、偶数を2とおくと 1,2,1,2.. 1,1,1,2... 2,2,2,1... 1,1,1,2... などの形がランダムに100個並べるようにしたいです。任意に1,2,1,2などに並べるのではなく。 つまり偶数と奇数の順番も条件のもとでランダムにしたいです。 言葉足らずですみません。
yambejp

2022/01/17 01:13 編集

それはわかっています たとえば完全にランダムを重視すると 1,1,1,2,1,1,1,2・・・的なつながりになると最後に偶数が余って4つ以上つながる可能性があり 調整が必要になります。その時点でランダム処理ではなくなるということです
shihatu

2022/01/17 01:20

確かにそのとおりです。厳密にはランダムな処理ではないですね。タイトルの誤植をお詫びします。 であれば、1,1,1,2,1,1,1,2の並べ方を'偶数もしくは奇数が4回以上続かないように並べる'という条件(1が50個2が50個)のもとで考えるとどういったアルゴリズムになりそうでしょうか。
yambejp

2022/01/17 05:13

サンプルをjsのソースにまとめました 最終結果として4パターン必要なのでそれを考慮してあります ・偶数ではじまり、偶数でおわる ・偶数ではじまり、奇数でおわる ・奇数ではじまり、偶数でおわる ・奇数ではじまり、奇数でおわる cntの数字を調整してもらえば連続の上限が変更できるはずです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問