プログラミングのお題スレ Part14
■ このスレッドは過去ログ倉庫に格納されています
あなたが解けない C/C++/Java/C#/JavaScript の問題を有償で片付けるスレッドです 有償で片付けるスレッドに貼り付けるのはよろしくないね 有償で片付けてほしくて出題してるわけじゃないでしょ 問題の窃盗だよ >>59 Perlは配列に対するexistsやdefinedは呼び出せるが振る舞いは不明確で「強く」非推奨となっているので この場合では問題なくとも@pはリストではなく代わりにハッシュ%pを使って実装するべきだった >>65 ハッシュにしたほうが良いのは@pじゃなくて@sの方だったわ >>64 バカチョンには何を言っても無駄だと思うよ 聞く耳持たない分からず屋の馬鹿だからバカチョンなんだから >>64 >>27 に理由が書かれていたが、一ヶ所に纏めておくと便利だなんてのは個人の都合であって、他の人にはわざわざ間接参照を強いることになるのだから、ほんとに身勝手な奴だと思う。 >>27 纏めておくのは他所で勝手にやれ、このスレにはコードだけを貼れよ。お前の手間なぞ知ったことではない。 >>62 折角まとめるんなら、回答の方も >> でリンクを貼って欲しいな。 >>70 それは絶対にやらないんじゃね 奴は自分のことしか考えてないから だから自己愛 永遠に人から煙たがられる存在 >>11 は、多角形の中のドットの内外判定問題と言うのが確立されてるみたいね。 色んな方法があるみたいだが、簡単なのは、 Crossing Number Algorithm らしい、ググってみると結構コンパクトなコード。 他も見てみたが、問題は境界線上にある点は多角形外と判定する事。 だから、そのままのロジックに手を入れないとした場合、使う側としてどう解決したら良いんだろう。 直行正方形を1ドットずつ大きくしてから回転させる? それとも、多角形の中の多角形問題の方が適してるのかな? この問題は結構勉強になる。 問題のイメージを掴むために、図形表示までやり始めたよ。 表示するとより楽しくなる。 >>71 そこまで悪い人間では無さそうだけどな、おだてれば猿も木に登るタイプだとみた。 高い木に登ってもらおう。 ググラないで考えようとしていたけど、 ヒントを目にしてしまった気分 いやべつにいいけどさ Q. クソ問題とは何ですか? A. 問題の解釈を巡って議論や煽り合いが10レス以上続く、バカが投稿した不備のある問題のことです。 >>47 Ruby ("HELLO".."WORLD").each{|v| puts v} >>72 https://dotup.org/uploda/dotup.org1853571.cpp.html とりあえず図形表示。 一応内部の点は除去して、凸包を表示するような感じにしてる。 左クリックで頂点追加、右クリックで全削除、中クリックでリセット 操作しながらいろいろ検討してるけど、さっぱり思いつかない。 >>9 Ruby def sumnum(n) (0..4).map{|i| ("1"*n +"0"*i).to_i} end >>78 Windows じゃないと動かないようだけど見やすいようにideonに張ってみた。 https://ideone.com/gJVREH 凸包と言うんだね。 2次元の凸包を求めるアルゴリズムと応用について https://matsu7874.hatenablog.com/entry/2018/12/17/025713 凸包(convex hull)とは,与えられた点をすべて包含する最小の凸多角形(凸多面体)のこと. -------- 凸包が求められても難しいね。 凸包内の点を削除して計算時間を削減できる効果はあるかもしれないけど。 凸包が求められれば、頂点の並びも整列するので 形状を分割して余弦定理とかから導けないかなって思ったんだよね ちなみに、最小を求めるだけならある角度から見た凸包の一次元への投影と、直交する角度からの一次元への投影を180度回しながら調べれば出せると思うけど、分割の粒度の問題で、本当に最小が取れる保証はないね >>76 試しに Perl でも 文字列 .. 文字列 をやってみたらできたよ。 こんなことできたとは。知らないまま20年以上使ってたよ。w >前スレの920 頭を使った。Ruby で、 str = "-6 3 9 5 3 -7" original_ary = str.split.map!( &:to_i ) # 各要素は整数型 hash = original_ary.each_with_object( { } ) { | num, h | h[ num ] = true } sorted_ary = hash.sort # キーでソートする #=> [[-7, true], [-6, true], [3, true], [5, true], [9, true]] # Enumerator#with_index(offset = 0) sorted_hash = sorted_ary.each.with_index( 1 ) { | elem, idx | elem[ 1 ] = idx }.to_h # p sorted_ary #=> [[-7, 1], [-6, 2], [3, 3], [5, 4], [9, 5]] # p sorted_hash #=> {-7=>1, -6=>2, 3=>3, 5=>4, 9=>5} results = original_ary.map{ | num | sorted_hash[ num ] } puts results.join( " " ) #=> 2 3 5 4 3 1 >>70-71 アンカーが多すぎると投稿できないのです、ただそれだけです >>73 >おだてれば猿も木に登るタイプだとみた。 痛いところを突きますね… >2 3 5 4 3 1 これが、 2 3 6 5 3 1 みたいに、4 が無くなる・飛ばされるランキングだと、もっとややこしい!w 前スレの920 Ruby def f(a) b={} a .dup.sort.each{|v|b[v]=b.size+1 if not b.key v} a.map{|v|b[v]} end p f([-6,3,9,5,3,-7]) [2, 3, 5, 4, 3, 1] >>34 >>79 一休さんみたいなトンチの効いた回答で、それはそれで楽しめました。 改めて問題を書き直します。 各桁を足し合わせたら引数で与えられた数になる数の集合全体から小さい順に(可能なら=0対策)5個返す関数を作れ。 例: sumnum 12 > [39,48,57,66,75] <- 3 + 9 = 12, 4 + 8 = 12, 5 + 7 = 12, 6 + 6 = 12, 7 + 5 = 12 苗字で漢字の「口」を「くち」ではなく「ぐち」と読むのは 井口、矢口、田口の3つだけ これマメな >>90 Haskell import Data.Char要らんかった。 take 5も問題と違うけど外に追い出した方が応用効きそう。 main = (print.take 5.sumnum) 12 sumnum 0 = [0] sumnum n |n < 0 = error "Please n >= 0 number" sumnum n = [x | x <- [1..], n == sum [read [a]| a <- show x]] >>95 OCamlで無限リスト処理どうすんだろと疑問だったので、後で精読させて頂きますm(_ _)m >>92 谷口 関口 合口・相口・藍口・青口・赤口・秋口・明口… https://name.sijisuru.com/Fname/search?option=1& ;moji=%E5%8F%A3&pages=0&kanjilen=0&kanalen=0&romalen=0 >>97 もう相手にすんな。お題にするなら、 その9つの名前の読み仮名のあいうえお順に並べよ。 谷口・関口・合口・相口・藍口・青口・赤口・秋口・明口 読み仮名を持ってくるのが難しそうだけどな。 aを要素の型がIntである長さNの配列、k、cを型がIntである変数とする。 {P}a[a[k]]=c;{a[a[k]]!=c} Hoare tripleが成立するためのなるべく弱いPを示せ >>99 教えてください P は何ですか? { } とは何を表しているのですか? >{P}a[a[k]]=c;{a[a[k]]!=c} sumnum、引数に10000とか与えたら答え返ってこなさそう 引数に1億とかは文字列長が千万とかになるから無理でも仕方ないけど、1万位は対応したいね >>103 知らない言語ばかりでよく読めてないんだが、今までの提出って1から順に試してね? それだと当然結果が返ってこないが 違ったらすまん >>92 は「必ずレスがもらえるレス」として有名な文らしいな 案の定わんさかレスの付いてること >>108 この凸包図を眺めてると、正解の正方形は 左辺の一番長い線を1辺とした正方形になりそうだが、それをどうやって求めるのか。 How to find the minimum-area-rectangle (MAR) fitted on the given points? https://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points 最初に書いた人は、凸包を求めて重心を中心として1度ずつ回転させるやり方を考えたらしいが、下の方で良い解法のコメントが付いてた。 https://i.stack.imgur.com/ExZl3.png 少しずつ回転させるのではなくて、長方形の1辺は必ず凸包の辺のどれかと重なってるはずだから、凸包の辺の角度だけをとって試せば良いとのこと。 これなら重心を求める必要もないし、時間はかからない。 長方形が求まったら、座標系の中に入る正方形にすれば良いがはみ出してたら、参考解かな。 このアルゴリズムは、 The algorithm you are looking for is known in polygon generalisation as "smallest surrounding rectangle". 凸包最小長方形の解法とでも言えば良いのかな。 >>109 正方形を求める場合で凸包がひし形の場合、その方法はうまくいかないきがす? 今回のアルゴリズムは、最小の正方形を求める方法だけじゃなくて、グラフの境界との交差判定もあるから 最小の求め方だけではなく、2番め以降についても正しく判定できないといけない上に、回答が一つに定まらない可能性もあるんだよね 与えられた点を全て含む凸包全体からなる集合の濃度は明らかに連続体濃度なんだから2番目なんて存在しないぞ >>112 書いててあれ?と思てったけど、たしかにそうだ。 俺では解けなさそうだ。 >>111 1辺から正方形を作る場合は、その正方形が全ての凸包の頂点を全て含むような大きさでなければならない。 この場合6辺あるから、そのような6つの正方形を作ってその中の最小のものを求めることになる。 面倒なのはそれが座標系に入らないといけないから場合によっては辺に平行移動しないといけないかも知れない。 すると、>>112 の言うように正方形の位置は変わるかもしれないけど、辺の長さが合ってれば正解だろうね。 (この場合は座標系に入るだろうからとりあえずは平行移動は考えないでも良いかも) >>110 どんな凸包体でも求まるよ。 1辺の長さが凸包体の辺の長さと一致させるわけじゃないよ。 全ての頂点を含む直方体を作る。 この求め方も工夫が必要そう。 1辺を伸ばした直線上に全ての頂点から垂線を引いて、一番外の距離を直方体の1辺とするんだろうな。 同じように他辺も求める。 >>116 雑な書き殴りですまん https://i.imgur.com/v8rWTSf.png さらにややこしいのは、凸包の頂点が正方形の辺上に位置して、 頂点に存在しないことのほうが多いのも難くする要因の一つ >>11 色々見たけど、画像認識の境界を探す為にある程度人気のある話題みたいだが、完全を求めるのではなく、だいたいで良いからスピードの速いのが良いとしてるみたいだね。 境界自体があやふやなものだし。 厳密にやるとしても、長方形と正方形ではかなり条件が違う。 全ての点が正方形に入るのなら、一つの候補は凸包の対角上の点が一番離れているところを正方形の対角とした正方形が一つの候補ではないだろうか。 直交正方形が最大だからそこまでを調べれば良いけど、それだけをしらみつぶしに調べてどれだけ時間がかかるかだな。 それをはみ出る点がある場合にどうゴニョゴニョするかだけど、条件が絞れればスピードは速くなる。 一般的にはポイント数は膨大な数だから、条件を絞り込む方法が重要になりそう。 しかし、こんな例題はどこにでもありそうで殆どサンプルがないのは時間がかかりすぎて簡単に試せないのかな、今回はポイント数が少ないからそれほどではないとは思うけど。 >>119 文章が変な順になっててごめん。 全ての点が正方形に入るのなら、一つの候補は凸包の対角上の点が一番離れているところを正方形の対角とした正方形が一つの候補ではないだろうか。 それをはみ出る点がある場合にどうゴニョゴニョするかだけど、条件が絞れればスピードは速くなる。 直交正方形が最大だからそこまでを調べれば良いけど、それだけをしらみつぶしに調べてどれだけ時間がかかるかだな。 計算両を優先するなら、座標軸を基準にとって大雑把に取るべきじゃないのかな これなら、ゲームのコリジョン検出で使われる方法そのままだし 点の数は関係なくね? 任意の3点を選んでその内部にある点は無いものとして考えても同じなんだから いや、関係あるか 頂点のめちゃくちゃ多い凸多角形になったら計算量明らかに増えるもんな >>11 なんかかなりの難問に思えてきたな。 解法への足がかりが見えない。 凸包までは比較的簡単にたどり着いたけどそれからが闇の中。 凸包の重心が何か使えるだろうか? 最小包含円 という言葉もあるようだが、少なくとも 正方形の辺はこの円の直径以下。 >>124 取り敢えずこの問題を 『凸包正方形 』 とでも呼びますか。 >>112 連続体濃度でかつ二番目に小さな値のある集合 {0, 1} ∪ (2, ∞) >>11 ポイントが(136,577), (110,927)の2つだけならどうなる? 以下はオレなりに考えた仮説 1)2点で正方形の内側に接するのは何らかの平べったい形、対角にて頂点が接するので45° 2)3点で接するのは、細長い三角形あるいはそれに準じた形、角度の計算は…?不明 または凸包の一辺が正方形の辺に接する形 3)4点で接するのは、細長い三角形あるいはそれに準じた形、角度の計算は…?不明 または凸包の一辺が正方形の辺に接する形 4)5点以上で接する場合は、凸包の一辺が正方形の辺に接する 「対角にて頂点が接する形の角度は45°」 「凸包の一辺が正方形の辺に接する形は凸包の辺の角度」 これらは角度が分かるので回転変化・逆変換を使って 外側の最小の斜め正方形の候補を探索することは可能だが、 角度が良く分からない形の解法が、まだ見出せていない 凸包の一辺が正方形の辺に接するおよび二点が対角に接する場合に限った解法 なら難しくないんだがな… >>129 それは正方形が(0,0)-(999,999)からはみでてまうな >>11 外側の正方形 Perl5、但し>>130 >>131の「凸包の一辺が正方形の辺に接する」または「細い菱形のような形が 正方形の対角2点で接する」場合について求てみた。凸包を求める処理は略し、二点間の辺を総当りで計算している。 use List::Util qw{min max pairkeys pairvalues}; @s=qw{136 577 110 927 472 199 157 808 388 598 94 31 388 157 325 409 787 897 850 598}; @X = pairkeys @s; @Y = pairvalues @s; sub sp {$_[0]*$_[2] + $_[1]*$_[3]} sub rt { @e = (cos $th, -sin $th); @f = (sin $th, cos $th); my @x = map{sp @e, $X[$_], $Y[$_]} 0..$#X; my @y = map{sp @f, $X[$_], $Y[$_]} 0..$#Y; @x = (min(@x), max(@x)); @y = (min(@y), max(@y)); $h = (max $x[1] - $x[0], $y[1] - $y[0]) / 2; $cx = ($x[1] + $x[0]) / 2; $cy = ($y[1] + $y[0]) / 2; @x = ($cx - $h, $cx + $h); @y = ($cy - $h, $cy + $h); ($e[1], $f[0]) = (-$e[1], -$f[0]); @x = map{sp @e, $x[$_], $y[$_]} 0..1; @y = map{sp @f, $x[$_], $y[$_]} 0..1; @x = (min(@x), max(@x)); @y = (min(@y), max(@y)); (\@x, \@y, 2*$h) } for $i (0..@X-2) { for $j ($i+1..$#X) { ($dx, $dy) = ($X[$j] - $X[$i], $Y[$j] - $Y[$i]); ($dx, $dy) = (-$dx, -$dy) if $dx < 0; $l = sqrt($dx*$dx + $dy*$dy); $th = $dx > abs($dy) ? -atan2($dy, $dx) : atan2($dx, $dy); ($X, $Y, $w) = &rt; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,l,$l,th,$th,X,$X,Y,$Y,w,$w}; $th += 3.14159265358979/4; ($X, $Y, $w) = &rt; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,l,$l,th,$th,X,$X,Y,$Y,w,$w}; } } @t = sort{$a->{w}<=>$b->{w}} grep{0<=$_->{X}[0]and$_->{X}[1]<=999 and 0<=$_->{Y}[0]and$_->{Y}[1]<=999} @t; do {@x = @{$t[$_]->{X}}; @y = @{$t[$_]->{Y}}; printf"%d: (%7.3f, %7.3f)-(%7.3f, %7.3f): w=%3.3f\n",$_+1,$x[0],$y[0],$x[1],$y[1],$t[$_]->{w}} for 0..5; >>133 の実行例 ~ $ perl 14_11.pl 1: ( 48.607, 27.043)-(863.062, 983.177): w=891.576 2: ( 45.920, 20.484)-(869.713, 849.356): w=892.353 3: ( 32.627, 29.170)-(901.066, 949.457): w=895.142 4: ( 24.000, 31.000)-(920.000, 927.000): w=896.000 5: ( 24.000, 31.000)-(920.000, 927.000): w=896.000 6: ( 14.845, 32.823)-(931.567, 907.397): w=896.130 検算してないので、もしバグっていたらゴメンチャイ、(ゝω・) テヘペロ >>133 スマソ、「正方形の4点の座標を示せ」と書かれていたので、出力処理を少し修正 use List::Util qw{min max pairkeys pairvalues}; @s=qw{136 577 110 927 472 199 157 808 388 598 94 31 388 157 325 409 787 897 850 598}; @X = pairkeys @s; @Y = pairvalues @s; sub sp {$_[0]*$_[2] + $_[1]*$_[3]} sub rt { @e = (cos $th, -sin $th); @f = (sin $th, cos $th); my @x = map{sp @e, $X[$_], $Y[$_]} 0..$#X; my @y = map{sp @f, $X[$_], $Y[$_]} 0..$#Y; @x = (min(@x), max(@x)); @y = (min(@y), max(@y)); $h = (max $x[1] - $x[0], $y[1] - $y[0]) / 2; $cx = ($x[1] + $x[0]) / 2; $cy = ($y[1] + $y[0]) / 2; @x = ($cx - $h, $cx + $h); @y = ($cy - $h, $cy + $h); ($e[1], $f[0]) = (-$e[1], -$f[0]); @x = map{sp @e, $x[$_], $y[$_]} 0..1; @y = map{sp @f, $x[$_], $y[$_]} 0..1; @x = (min(@x), max(@x)); @y = (min(@y), max(@y)); (\@x, \@y, 2*$h) } for $i (0..@X-2) { for $j ($i+1..$#X) { ($dx, $dy) = ($X[$j] - $X[$i], $Y[$j] - $Y[$i]); ($dx, $dy) = (-$dx, -$dy) if $dx < 0; $l = sqrt($dx*$dx + $dy*$dy); $th = $dx > abs($dy) ? -atan2($dy, $dx) : atan2($dx, $dy); ($X, $Y, $w) = &rt; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,l,$l,th,$th,X,$X,Y,$Y,w,$w}; $th += 3.14159265358979/4; ($X, $Y, $w) = &rt; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,l,$l,th,$th,X,$X,Y,$Y,w,$w}; } } @t = sort{$a->{w}<=>$b->{w}} grep{0<=$_->{X}[0]and$_->{X}[1]<=999 and 0<=$_->{Y}[0]and$_->{Y}[1]<=999} @t; do {@x = @{$t[$_]->{X}}; @y = @{$t[$_]->{Y}}; printf"%d: (%6.3f, %6.3f), (%7.3f, %6.3f), (%6.3f, %7.3f), (%7.3f, %7.3f): w=%3.3f\n", $_+1,$x[0],$y[0],$x[1],$y[0],$x[0],$y[1],$x[1],$y[1],$t[$_]->{w}} for 0..5; >>135 実行結果 ~ $ perl 14_11.pl 1: (48.607, 27.043), (863.062, 27.043), (48.607, 983.177), (863.062, 983.177): w=891.576 2: (45.920, 20.484), (869.713, 20.484), (45.920, 849.356), (869.713, 849.356): w=892.353 3: (32.627, 29.170), (901.066, 29.170), (32.627, 949.457), (901.066, 949.457): w=895.142 4: (24.000, 31.000), (920.000, 31.000), (24.000, 927.000), (920.000, 927.000): w=896.000 5: (24.000, 31.000), (920.000, 31.000), (24.000, 927.000), (920.000, 927.000): w=896.000 6: (14.845, 32.823), (931.567, 32.823), (14.845, 907.397), (931.567, 907.397): w=896.130 検算してないので、もしバグっていたらゴメンチャイ、(ゝω・) テヘペロ >>136 なんか変、バグってるスマソ、直すことが出来たら書き込みます >>11 外側の正方形 Perl5 凸包の辺が正方形の辺に接するまたは対角二点で接する場合、>>135 の露骨なバグ一個修正 use List::Util qw{min max pairkeys pairvalues}; @s=qw{136 577 110 927 472 199 157 808 388 598 94 31 388 157 325 409 787 897 850 598}; @X = pairkeys @s; @Y = pairvalues @s; sub sp {$_[0]*$_[2] + $_[1]*$_[3]} sub rt { @e = (cos $th, -sin $th); @f = (sin $th, cos $th); my @x = map{sp @e, $X[$_], $Y[$_]} 0..$#X; my @y = map{sp @f, $X[$_], $Y[$_]} 0..$#Y; @x = (min(@x), max(@x)); @y = (min(@y), max(@y)); $h = (max $x[1] - $x[0], $y[1] - $y[0]) / 2; $cx = ($x[1] + $x[0]) / 2; $cy = ($y[1] + $y[0]) / 2; @x = ($cx - $h, $cx + $h, $cx - $h, $cx + $h); @y = ($cy - $h, $cy - $h, $cy + $h, $cy + $h); ($e[1], $f[0]) = (-$e[1], -$f[0]); @x = map{sp @e, $x[$_], $y[$_]} 0..3; @y = map{sp @f, $x[$_], $y[$_]} 0..3; (\@x, \@y, 2*$h) } for $i (0..@X-2) { for $j ($i+1..$#X) { ($dx, $dy) = ($X[$j] - $X[$i], $Y[$j] - $Y[$i]); ($dx, $dy) = (-$dx, -$dy) if $dx < 0; $l = sqrt($dx*$dx + $dy*$dy); $th = $dx > abs($dy) ? -atan2($dy, $dx) : atan2($dx, $dy); ($X, $Y, $w) = &rt; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,l,$l,th,$th,X,$X,Y,$Y,w,$w}; $th += 3.14159265358979/4; ($X, $Y, $w) = &rt; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,l,$l,th,$th,X,$X,Y,$Y,w,$w}; } } @t = sort{$$a{w}<=>$$b{w}} grep{0<=min@{$_->{X}}and max@{$_->{X}}<=999 and 0<=min@{$_->{Y}}and max@{$_->{Y}}<=999} @t; do {@x = @{$t[$_]{X}}; @y = @{$t[$_]{Y}}; printf"%d: (%7.3f,%7.3f), (%7.3f,%7.3f), (%7.3f,%7.3f), (%7.3f,%7.3f): w=%7.3f, th=%7.3f°\n", $_+1,$x[0],$y[0],$x[1],$y[1],$x[2],$y[2],$x[3],$y[3],$t[$_]{w},$t[$_]{th}*180/3.14159265358979} for 0..4; >>138 実行例 ~ $ perl 14_11.pl 1: ( 32.627, 29.170), (927.382, 55.475), ( 6.310,923.152), (901.066,949.457): w=895.142, th= -1.685° 2: (920.000,927.000), ( 24.000,927.000), (920.000, 31.000), ( 24.000, 31.000): w=896.000, th=180.000° 3: ( 24.000, 31.000), (920.000, 31.000), ( 24.000,927.000), (920.000,927.000): w=896.000, th= 0.000° 4: ( 14.845, 32.823), (910.733, 11.994), ( 35.680,928.226), (931.567,907.397): w=896.130, th= 1.332° 5: ( 18.819, 32.332), (914.819, 16.335), ( 34.819,928.046), (930.819,912.049): w=896.143, th= 1.023° ちゃんと検算してないので、もしまだバグがいたらゴメンチャイ、(ゝω・) テヘペロ 検算方法考えた方がいいのかも。ちなみにwは正方形の幅、thは回転各[deg] >>11 の内側の正方形についてはまだ考えていない。 >>11 おもろいな、初級問題だと文法の練習としてそれなりに勉強になる。 こう言うのはそれを超えていろんなパッケージ/ライブラリを駆使することになるから一皮剥けて勉強になる。 解けるか解けないか判らないけど楽しんでる。 勿論こう言うのは、言語の問題ではなく、ロジックの問題だと解っているんだが、ヒントとなる数字を出せるのは言語の力にもよるからそれはそれなりに面白い。 図形は直感的に推論が正しいかどうか判るから面白い。 https://i.imgur.com/cCazfFe.jpg 凸包の重心は使えなさそうだな。 >>139 なんとなく変に感じるんだが。 https://i.imgur.com/3ioZWjZ.jpg この場合の正方形の一辺は、左側の凸包の線そのものになると思うんだけど。 つまり、左下端が、( 94,31 )、上端が(110,927) にならないかな? >>140 ごめん、同じ画像を二つ上げてしまった。 >>140 図をありがとう scriptを(94, 31) - (110, 927)の辺に傾けてこの角度における最小の正方形だけを計算するようなおして 計算したら 5: ( 18.819, 32.332), (914.819, 16.335), ( 34.819,928.046), (930.819,912.049): w=896.143, th= 1.023° になりました。 >>144 それはおかしい。 直行正方形の辺の長さが896だから、896以下にならなければならない。 >>11 1)のみ やってみた。 図 https://codepen.io/dokokade/full/WBzgrZ ※ 途中で完全にJavaScriptのお遊びになってしまった。 (計算は別プログラムで、そのログを図にした) 一辺 = 890.70993168302 四点 x: [ 0.8027676391, 82.9114960624, 969.828819782, 887.7200913596] y: [916.8907759982, 29.9734522778, 112.082180701, 998.9995044215] >>146 あ、でも 右上の頂点は y = 998.9995044215 となってるけど、 正確には y=999 とぶつからなければいけないよね。 少し誤差が大きすぎるような気がするけどこんなもの? >>140 この図の(388,157)は(388,598)の誤記? >>149 間違っていないでしょ。 両方あるよ。 xys [[136 577] [110 927] [472 199] [157 808] [388 598] *** [ 94 31] [388 157] *** [325 409] [787 897] [850 598]] https://i.imgur.com/9emHzzD.jpg >>145 凸包の一辺(94,31)-(110,927)のみに着目し、この辺が垂直となる様に座標を1.023°回転して から点郡を囲む矩形領域を求め、その長方形を正方形になるように短い辺を伸ばす処理は省いて 長方形のまま元の座標系に逆変換し4頂点座標を見たところ、 use List::Util qw{min max}; use Math::Trig; @X = qw{94 110}; # 787 850 472 388}; @Y = qw{31 927}; # 897 598 199 598}; sub sp {$_[0]*$_[2] + $_[1]*$_[3]} for $i (0..@X-2) { for $j ($i+1..$#X) { ($dx, $dy) = ($X[$j] - $X[$i], $Y[$j] - $Y[$i]); ($dx, $dy) = (-$dx, -$dy) if $dx < 0; $th = $dx > abs($dy) ? -atan2($dy, $dx) : atan2($dx, $dy); @e = (cos $th, -sin $th); @f = (sin $th, cos $th); my @x = map{sp @e, $X[$_], $Y[$_]} 0..$#X; my @y = map{sp @f, $X[$_], $Y[$_]} 0..$#Y; @x = (min(@x), max @x); @y = (min(@y), max @y); $w = max($x[1] - $x[0], $y[1] - $y[0]); ($e[1], $f[0]) = (-$e[1], -$f[0]); @x = map{sp @e, $x[$_], $y[$_]} 0,1,0,1; @y = map{sp @f, $x[$_], $y[$_]} 0,0,1,1; #next if min@x<0 or 999<max@x or min@y<0 or 999<max@y; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,th,$th,X,[@x],Y,[@y],w,$w} } } @t = sort{$$a{w}<=>$$b{w}} @t; do {@x = @{$_->{X}}; @y = @{$_->{Y}}; printf"%d: (%7.3f,%7.3f), (%7.3f,%7.3f), (%7.3f,%7.3f), (%7.3f,%7.3f): w=%7.3f, th=%7.3f°\n", ++$k,$x[0],$y[0],$x[1],$y[1],$x[2],$y[2],$x[3],$y[3],$$_{w},rad2deg $$_{th}} for @t; ~ $ perl 14_11_2.pl 1: ( 94.000, 30.990), (110.000, 30.990), ( 94.000,926.704), (110.000,926.704): w=896.143, th= 1.023° となったので、今のところ計算は合っていると思う。おかしく感じたのは長方形を正方形になるように短い辺を伸ばした座標の シフトによるものだと思う。しかし、この長方形⇒正方形補正が曲者で、より小さい正方形であるにもかかわらず長方形の 短辺を両側に均等に伸ばすと頂点が0〜999の範囲をこえてしまうものがあるらしく、不均等に伸ばすようにすれば より小さい正方形を見出せるかもしれない。 >>150 外接円を描いてみたけど、利用方法を見つけられなかった。 むしろ [ 94 31] [787 897] の対角を直径とする最小包含円 からかな? 以下は試作実験programと結果 @凸包の辺の角度にのみ傾ける(それ以外の角度は略) A長方形⇒正方形補正は略 B頂点座標が0〜999の範囲外も出力 use List::Util qw{min max}; use Math::Trig; @X = qw{94 110 787 850 472 388}; @Y = qw{31 927 897 598 199 157}; sub sp {$_[0]*$_[2] + $_[1]*$_[3]} for $i (0..@X-2) { for $j ($i+1..$#X) { ($dx, $dy) = ($X[$j] - $X[$i], $Y[$j] - $Y[$i]); ($dx, $dy) = (-$dx, -$dy) if $dx < 0; $th = $dx > abs($dy) ? -atan2($dy, $dx) : atan2($dx, $dy); @e = (cos $th, -sin $th); @f = (sin $th, cos $th); my @x = map{sp @e, $X[$_], $Y[$_]} 0..$#X; my @y = map{sp @f, $X[$_], $Y[$_]} 0..$#Y; @x = (min(@x), max @x); @y = (min(@y), max @y); $w = max($x[1] - $x[0], $y[1] - $y[0]); ($e[1], $f[0]) = (-$e[1], -$f[0]); @x = map{sp @e, $x[$_], $y[$_]} 0,1,0,1; @y = map{sp @f, $x[$_], $y[$_]} 0,0,1,1; #next if min@x<0 or 999<max@x or min@y<0 or 999<max@y; push @t, +{i,$i,j,$j,dx,$dx,dy,$dy,th,$th,X,[@x],Y,[@y],w,$w} } } @t = sort{$$a{w}<=>$$b{w}} @t; do {@x = @{$_->{X}}; @y = @{$_->{Y}}; printf"%d: (%7.3f,%7.3f), (%7.3f,%7.3f), (%7.3f,%7.3f), (%7.3f,%7.3f): w=%7.3f, th=%7.3f°\n", ++$k,$x[0],$y[0],$x[1],$y[1],$x[2],$y[2],$x[3],$y[3],$$_{w},rad2deg $$_{th}} for @t[0..4]; 1: (752.170,710.324), ( 94.000,710.324), (752.170, -8.662), ( 94.000, -8.662): w=873.451, th=168.102° 2: ( 70.342, 31.983), (863.100, 31.983), ( 70.342,891.839), (863.100,891.839): w=895.830, th= 2.537° 3: ( 94.000, 30.990), (855.637, 30.990), ( 94.000,913.391), (855.637,913.391): w=896.143, th= 1.023° 4: (699.348,547.478), ( 94.000,547.478), (699.348,-34.520), ( 94.000,-34.520): w=945.899, th=160.148° 5: ( 94.000, 29.184), (671.086, 29.184), ( 94.000,1007.681), (671.086,1007.681): w=978.102, th=-23.199° 真の極小解は中途半端な角度にあるのか… >>148 146は、ヒュースリックス解だから、まだ小さくなると思う。 でも、あと1くらいだと思う ( これが厳密解を求めるやる気が、無くなる原因) 少しずるして、この問題に過剰最適化させて、 890.7003209442369にした。 図 https://codepen.io/dokokade/full/WBzgrZ >>154 これ、凸包の辺の角度にのみ傾けてない、凸包の全頂点の組み合わせエッジの角度に傾けている。 まいいや、大差ない >>125 >>11 の問題1 に名前を与えるならさしずめ、最小包含正方形 かな。 >>155 無理を言ってごめん、答えの誤差をなくすために、最終座標は整数の xy 座標に出来るかな。 中心からの距離を切り上げて整数にする感じになると思うけど。 こういう問題って、極小・最小解にいたる連続的な解空間形成してなけりゃ収束計算もできないし かといって解析的あるいはロジカルな求解法が見出せなけりゃ、最後はヒューリスティックあるいはランダムwalk あるいはRISMみたいな外挿的に探索するしかないのだろうか… ないんだろうなたぶん。そんなきがす ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる