moduleNS=Set.Make(structtypet=intletcompare=Pervasives.compareend)moduleSS=Set.Make(structtypet=NS.tletcompare=NS.compareend)moduleLS=Set.Make(structtypet=SS.tletcompare=SS.compareend)letmake_set_with_sumn=letrecloopsetsum=function|0->(set,sum)|n'->loop(NS.addn'set)(sum+n')(n'-1)inloopNS.empty0nletns_mapfns=NS.fold(funsacc->NS.add(fs)acc)nsNS.emptyletss_mapfss=SS.fold(funsacc->SS.add(fs)acc)ssSS.emptyletls_mapfls=LS.fold(funsacc->LS.add(fs)acc)lsLS.emptyletrectake_subsetssetnumlimit=ifNS.is_emptyset||NS.cardinalset<num||NS.chooseset>limitthenSS.emptyelsebeginmatchnumwith|1->ifNS.memlimitsetthenSS.singleton(NS.singletonlimit)elseSS.empty|nwhenn>1->letresult=refSS.emptyinNS.iterbeginfuni->letset'=NS.removeisetinletnum'=num-1inletlimit'=limit-iinbeginmatchtake_subsetsset'num'limit'with|swhenSS.is_emptys->()|ss->result:=SS.union!result(ss_map(NS.addi)ss)endendset;!result|_->invalid_arg"num is required positive number."endletmake_setsn=ifn<2theninvalid_arg"required greater than or equal to 2.";letfull,max=make_set_with_sum(n*n)inletheads,_=make_set_with_sumninletdiff=NS.difffullheadsinletlimit=max/ninletsubsets=NS.foldbeginfuniacc->LS.add(ss_map(NS.addi)(take_subsetsdiff(n-1)(limit-i)))accendheadsLS.emptyinletinters=lethd=LS.choosesubsetsinlettl=LS.removehdsubsetsinLS.foldbeginfunssacc->letresult=refLS.emptyinLS.iterbeginfunss'->SS.iterbeginfunns->ifSS.for_all(funs->NS.is_empty(NS.intersns))ss'thenresult:=LS.add(SS.addnsss')!resultendssendacc;!resultendtl(SS.fold(funeacc->LS.add(SS.singletone)acc)hdLS.empty)inintersletns_printns=print_string"{ ";NS.iter(Printf.printf"%d, ")ns;print_string"}"letss_printss=SS.iterbeginfuns->ns_prints;print_string", "endss;print_newline()letls_printls=LS.iterss_printlsletexamn=LS.cardinal(make_setsn)letmain()=letnum=matchSys.argvwith|[|_;n|]->int_of_stringn|_->3inPrintf.printf"n = %d => %d patterns\n"num(examnum)let()=ifnot!Sys.interactivethenmain()
jijixi
#4817()
[
OCaml
]
Rating-2/2=-1.00
答が合ってるのかすら心配。
Mac OS X 10.5 / PPC G5/1.6GHz mem 1GB な環境で、
% time ./numbers.native 4
n = 4 => 151 patterns
./numbers.native 4 0.03s user 0.01s system 27% cpu 0.141 total
n = 5 は 5 分くらい待っても終わらなかったのであきらめた。
方針としては、
* 各セットの合計は 1 ~ n までの合計を n で割ったものになるので、そうなる組み合わせを生成
* 先頭が 1 ~ n のものが並ぶはずなので、そこまでしか計算しない
* OCaml の Set モジュールは整列済みなので、それを利用して多少枝刈りしているつもり
といった感じ。
n = 5 が終わらないのは、メモリ使用量の問題もありそうなので、完全なセットを作ってしまわずに逐次表示するようなアプローチにすれば、もう少し何とかなるかも。
でももう頭がパンクしそうなので、とりあえずこれで。
Rating-2/2=-1.00-0+
1 reply [ reply ]