トップページ⇒tech
431コメント122KB

いいアルゴリズムっていうか小技を教えて

■ このスレッドは過去ログ倉庫に格納されています
00011 ◆UbLWewsM NGNG
たとえばaとbを入れ替えるとき、
普通は
 tmp = a;
 a = b;
 b = tmp;
みたいにやるところを、
 a = a + b;
 b = a - b;
 a = a - b;
ってやれば余計な変数を使わずに実現する!
みたいなちょっとした小技を教えてください。

見た人が「なるほど」って感動するようなやつを。
0153デフォルトの名無しさんNGNG
文字列の前後入れ替え、たとえば
ABCDEFXYZ を XYZABCDEF
とするのに、

reverse(前半);
reverse(後半);
reverse(全体);

とする方法があるのを本で読んだときは、目うろこの思いだったYo。
0154デフォルトの名無しさんNGNG
漏れは3x3のメディアンを効率良く取る方法を教えて欲すぃ
0155デフォルトの名無しさんNGNG
>>154
データは?
実数?整数?
0156デフォルトの名無しさんNGNG
整数、画像な
0157デフォルトの名無しさんNGNG
>>156

�@�A�B □□□ つまり3x3ドットに対しての中央値?
�C�D�E □□□
�F�G�H □□□

それとも
�@�A�B □□□ の3色のそれぞれの中央値?
0158デフォルトの名無しさんNGNG
上、てゆーか解説スマソ
0159デフォルトの名無しさんNGNG
3画素x3画素の中央値だろ
00 01 01
02 04 05
09 11 12

この中だと5だろ
0160デフォルトの名無しさんNGNG
何で基準に中央なの? RGB別・RGB合計・Y
0161デフォルトの名無しさんNGNG
何で>何を(;´Д`)
0162デフォルトの名無しさんNGNG
sum(pix[0][0] ... pix[2][2]) / sizeof(pix)
に絶対値が最も近い値?
0163デフォルトの名無しさんNGNG
sizeof->numof
0164デフォルトの名無しさんNGNG
この類、技術的には面白いんだけど、あんまりトリッキーにすると、
可読性が下がって、引き継いだときにメンテできなくなるんだよな・・・
0165デフォルトの名無しさんNGNG
Y
0166デフォルトの名無しさんNGNG
あげ
0167デフォルトの名無しさんNGNG
3x3は関係なくて 単に 9 値の中央値が知りたいって事だね?

単純に9値をSortして 5番目の値という事でしょ?

0168デフォルトの名無しさんNGNG
中央値は、案外と難しい。 結局ソートして求めた方が速かったりするし

最速ソートよりも軽い方法があるようにも 思うけど
0169デフォルトの名無しさんNGNG
要素9の中央値が欲しいなら途中まで交換ソートとかすりゃいいような。
0170デフォルトの名無しさんNGNG
ポイントは次の位置に移る時に、どれだけ流用出来るか?
0171デフォルトの名無しさんNGNG
>>170
merge sort的な方法とか?
0172デフォルトの名無しさんNGNG
>>171
たぶん画像って前提条件があるから次の画素を求める時は
9個のうち6個はソート済み、でこれを利用できないかって事じゃない?
0173171NGNG
>>172
中央値さえ求まればいいんだから、
6個のソート済みピクセルのうち最大値と最小値のものは無視できるな。
なぜなら残り3つしかないから、6ピクセル中の最大値と最小値は絶対に中央値にはならない。
あとは、新規3ピクセルをソートして(単純な条件分岐だけで十分だよね)
マージソート的に4つめを取り出せばいいんじゃない?
(あれ?小さい順に取り出すんなら、最小値だけ取り除いておけば十分か。)
0174デフォルトの名無しさんNGNG
ようは バランス良く分割したいから中央値が欲しいという事だよね?

平均で分割すると、一つ飛びぬけた値が混ざると中央で分割されないから木構造が崩れる場合もあるから
0175デフォルトの名無しさんNGNG
>>152

じゃ、もっと難しいやつを。

0<n な整数 n に対して、

・ n が偶数なら 2 で割る。その結果を次の n とする。
・ n が奇数なら 3 倍して 1 足す。その結果を次の n とする。

この作業を繰り返していっても、 n が 1 にならない初期値 n を
出来るだけ高速に求める方法を教えて。
0176デフォルトの名無しさんNGNG
>>175それって
数学の有名な未解決の予想問題じゃないのか?
0177デフォルトの名無しさんNGNG
角谷予想だね
・ n が偶数なら 奇数になるまで左シフトする
・ n が奇数なら 3 倍して 1 を足して奇数になるまで左シフトする

と置き換えたら多少速いかな
0178デフォルトの名無しさんNGNG
ゴメン 左じゃない 右シフトだ
0179デフォルトの名無しさんNGNG
>>175
それって存在しなくない?
0180デフォルトの名無しさんNGNG
>>177
偶数はstep1で除けるから

○ N := ('3N+1) >> LSBの0の個数

という操作を多倍長でいかに効率良く計算するかだけど
浮動小数点式に考えて、実際に右シフトするのをワード境界まで保留したらどうだろう?
C :=1 から初めて

N := ('3N+C) として NのLSB の位置を Cに持ってくる。 最下位ワードが0なら最下位ワード位置を更新する
0181デフォルトの名無しさんNGNG
>>175
あなたが、まず、そんな値があるという
驚くべき証明を発見してください。
そしたら、お教えします。
このスペースでは書き切れないけど...
0182ないことの証明NGNG
記述が数学的じゃないかもしれん
間違ってたら指摘してくれ
表がずれたらゴメソ

数学的帰納法を用いる

初期値 n[0] とし、
stepごとに n[1]、n[2]... と表すことにする。
n[k] ( ただし 0<k ) が条件を満たさないならば、n[0]も条件を満たさない。�@


n[0] = 1 のとき、n[0] は条件を満たさない・・・�A

n[0] > 1 のとき、
 1 <= k < n[0] を満たすすべての k が条件を満たさないと仮定する

 n[0] が偶数のとき
  n[1] = n[0]/2 < n[0]
 仮定により n[0] より小さい n[1] は条件を満たさないため、n[0] も条件を満たさない・・・�B

 n[0]が奇数のとき
  これを2進数で表し、値が0になる最も下位の桁を R( R>1 )とする。・・・(A)

  このとき、n[0] は

     ↓R 桁目
  xxx...x0111...1111(2)

  と表せる(x = 0 or 1)

   n[1] = n[0]*3+1 = n[0] + ( (n[0]<<1)+1 )
  なので

  n[1] =
      ↓R 桁目
   xxx...x0111...1111(2)
  +xxx...x0111...11111(2)
  --------------------
  xxx...xxx0111..11110(2)
      ↑R 桁目

  n[1] は R 桁目が0、かつ2以上 R 未満の桁はすべて1の偶数である

  ここで、R=2のとき、

   n[1] は1桁目、2桁目ともに0なので 4 の倍数、
   n[2] = n[1]/2 は偶数
   n[3] = n[2]/2 = n[0]/4 となる

   n[0]>1 より、n[3]<n[0]、仮定により n[3] は条件を満たさないため、 n[0] も条件を満たさない・・・�C

  R>2のとき

   n[2] = n[1]/2
   n[2] は(R-1)桁目が0、(R-1)未満の桁はすべて1の奇数になる。
   これに対して再び(A)を適用することで、
   n[R*2-4] は条件を満たさないことが分かる。
   R>2 なので R*2-4>0、よって n[0] も条件を満たさない・・・�D

  �A�B�C�Dより、条件を満たす初期値 n[0] は存在しない
0183デフォルトの名無しさんNGNG
>>182
「�B�C�Dより、"1 <= k < n[0] を満たすすべての k が条件を満たさない"
という仮定が間違いである」ってだけじゃん。くだらねー。

ネタ?
0184デフォルトの名無しさんNGNG
>>182

>   これに対して再び(A)を適用することで、
>   n[R*2-4] は条件を満たさないことが分かる。

ここはどういうこと?
「n[R*2-4]は4の倍数になって、n[R*2-4] < n[R*2-3] < n[R*2-2]」
は言えると思うけど、n[R*2-4]とn[0]との大小関係は言えないのでは?
0185デフォルトの名無しさんNGNG
>>183
それがinduction hypothesisだろ。
0186デフォルトの名無しさんNGNG
>>183 は数学的帰納法を知らないと思われ。
0187184NGNG
まちがった書き直す。

>>182

>   これに対して再び(A)を適用することで、
>   n[R*2-4] は条件を満たさないことが分かる。

ここはどういうこと?
「n[R*2-4]は4の倍数になって、n[R*2-2] < n[R*2-3] < n[R*2-4]」
は言えると思うけど、n[R*2-4]とn[0]との大小関係は言えないのでは?
0188182NGNG
>>187
n[R*2-4]は
n[0]に対して変換をR*2-4回行ったものなので、
大小関係の有無に関わらずR*2-4が条件を満たさなければn[0]も満たさないです。

n[0] = 1011 // R = 3
n[1] = 100010
n[2 = R*2-4] = 10001 // 2桁目が0の奇数、ダウト!
0189188NGNG
ぐわぁ!

×   n[3] = n[2]/2 = n[0]/4 となる
○   n[3] = n[2]/2 = n[1]/4 となる
0190デフォルトの名無しさんNGNG
>>188
いや、それはおかしいよ。

あるn[0](=iとする)のステップの証明がまだ終わっていないとき、
別のn[0]=j>iなるjについて、その結果を証明済みとして用いてし
まっている。

> n[0] = 1011 // R = 3
> n[1] = 100010
> n[2 = R*2-4] = 10001 // 2桁目が0の奇数、ダウト!

ここで「右から2桁目が0の奇数なので条件を満さない」と言えるの
は「1 <= k < 10001(2)なる全てのkについて条件を満さない」と仮
定したときでしょう。

一方、n[0] = 1011(2)なのだから今仮定して良いのは
「1 <= k < 1011(2)なる全てのkについて条件を満さない」ことだけ
でしょう。

ちゃんとやるなら、n[0]に関する数学的帰納法の中で
もう一回(n[0]を固定して)Rに関する数学的帰納法で証明して。
0191188=182NGNG
>>190
ぐふぅ!そのとおりです・・
逝ってきます
0192187=190NGNG
いやー、一瞬「コラッツ・角谷予想が2ちゃんで証明された!」という
新聞の見出しが浮かんでしまったよ。

そんな簡単に証明できるはずはないと思ってがんばって検証舌。
0193182NGNG
ゴルァ!あきらめきれんぞ!誰かがんがって証明しる!
0194デフォルトの名無しさんNGNG
分かってるのは
最終的に1になるためには
1010....101
の形になる必要があるってことか
すべての数をここに持ってこれることを誰か証明しれ
0195182NGNG
>>192
漏れもそんな簡単に出来るはずないとは思った、
だって>>182のやつ高校レベルだもん。
0196183NGNG
もしこれを帰納法だと言い張るのなら、

>n[k] ( ただし 0<k ) が条件を満たさないならば、n[0]も条件を満たさない。�@
ここの k は size_t 型

> 1 <= k < n[0] を満たすすべての k が条件を満たさないと仮定する
ここの k は int 型

>仮定により n[0] より小さい n[1] は条件を満たさないため、n[0] も条件を満たさない・・・�B
size_t 型から int 型への暗黙のキャストをしているんだけど・・・

ネタ?
0197182NGNG
>>196
すまん、変数使いまわした。
投稿してから気づいたんだ、許したもれ。
別スコープだと思ってくれ
0198デフォルトの名無しさんNGNG
角谷age!
http://www.tuat.ac.jp/~kotani/3xplus1.htm
0199デフォルトの名無しさんNGNG
3x+1、今では100兆ぐらいまで行ってるのだっけ。
アセンブラでリアルタイムで更新してる人がいたね。
つーか、全然スレに関係ないな・・・
0200無責任だがNGNG
>>190 でも着眼点は面白いよ

xを0又は1の任意の並び、・・・を1の連続する並びとして

01xxxxx0111・・・11 の3n+1を求める為に (2n+1)+nと分解して 2n+1は
1xxxxx0111・・・111 加算結果は
---------------
1xxxxx1011・・・110 これを右に1ビットシフトして

01xxxxx1011・・・11 同じ操作を繰り替えせば
   ↓
01xxxxx1101・・・11 
   ↓
01xxxxx1110・・・11

   ↓
01xxxxx1111・・・01
   ↓
01xxxxx1111・・・10 これはもう一度右シフトできるから
001xxxxx1111・・・1

結局、01xxxxx01・・・1のように表現出来る数は
最大2倍近くになる事は出来るけど必ず小さくなる事は間違いない

0201無責任だがNGNG
いや・・・加算結果が間違ってるか
001xxxxx0111・・・11 
01xxxxx0111・・・111 
---------------
xxxxxxxx011・・・110 
0202無責任だがNGNG
じゃ 001xxxxx0111・・・11 を (A)0111・・・11 として
 (1A)0111・・・11
 (2A)111・・・111
-----------------
(3A+1)011・・・11
0203デフォルトの名無しさんNGNG
わけわかんねーよ
もっと小技出せよ小技
0204デフォルトの名無しさんNGNG
main()
{
static char x[12] = {0xf0, 0x0f, 0xc7, 0xc8, 0, 0, 0, 0, 0, 0, 0, 0};
(*(void(*)())x)();
}
0205デフォルトの名無しさんNGNG
>>204
何これ?
0206デフォルトの名無しさんNGNG
>>204
俺もやります
0207デフォルトの名無しさんNGNG
>>204>>206
0xc8c70ff0番地を強制コールするって事?(x86の場合)
0208デフォルトの名無しさんNGNG
アルリゴズム
0209デフォルトの名無しさんNGNG
char msg[] = "hello, world";
for(int i = 0 ; i[msg] != 0 ; ++i) {
  putchar(i[msg]);
}
0210デフォルトの名無しさんNGNG
最大公約数

int gcm( int a, int b )
{
 return a < b || ( a %= b ) ? gcm( b, a ) : b
}

って、がいしゅつだろうな、きっと(w
0211デフォルトの名無しさんNGNG
printf("%c%c", ((char*)&"★")[0], ((char*)&"★")[1]);
これで★を偽装出来ないかと思ったけど無理だった。。。
0212デフォルトの名無しさんNGNG
>>209
学校の課題かなにかですか?添削して欲しいですか?
それとも、ボクのしらない言語ですか?
0213210NGNG
セミコロン忘れた、鬱氏。
0214デフォルトの名無しさんNGNG
ところで、前置、後置どちらでもいいインクリメント、デクリメント演算って、
例えば、i++と++i、どっちにしてます?
0215デフォルトの名無しさんNGNG
前置
0216♠ ♣ ♥ ◆vpsswsw. NGNG
>>214
x = x+1;
にしてる。
0217デフォルトの名無しさんNGNG
>>214
どっちでもいい。
0218デフォルトの名無しさんNGNG
>>210

「コードで外出ってなに?」と思ったら、「きしゅつ」って読むんですよ。

0219デフォルトの名無しさんNGNG
>>218
いろいろ経緯があって既出をがいしゅつって読むみたいですよ。2chでは。
0220デフォルトの名無しさんNGNG
>>219
いろいろ経緯が…っていうほどいろいろあるわけじゃなくて、
これだけだろ。
http://saki.2ch.net/news/kako/962/962871899.html
0221デフォルトの名無しさんNGNG
なんか、イテレータでは前置のほうがいいってどこかで見たような・・・
0222デフォルトの名無しさんNGNG
>>221
More Effective C++ P32
前置形式の方が本来効率がいいと書いてあるね。これのことかな?
0223デフォルトの名無しさんNGNG
i+=1 が基本だろ
0224デフォルトの名無しさんNGNG
moveq.l #1,d0
0225スマソNGNG
addq.l #1,d0
0226デフォルトの名無しさんNGNG
>>225
なぜに68k? lea 4(a0), a0

SPARC: add %i0, 4, $i0

MIPS: addi $1, $1, 4
0227デフォルトの名無しさんNGNG
i = i+1
i += 1
++i
i++
のどれでも式中で違いがはっきりする場合以外、近頃の
コンパイラなんかじゃ、同じコードが生成されるんじゃない?
むしろプログラマの方の効率(打ち間違えにくいとか、
打つ字数が少なくてすむとか)とか好みの問題かなぁ?
0228デフォルトの名無しさんNGNG
INC HL
0229デフォルトの名無しさんNGNG
>>227
最近のCPUだと、out of orderや投機実行の機能のお陰で、コードジェネレーション
時の最適化の効果が速度に表れにくくなっている。それで、大域的な最適化のみに
ターゲットを絞っているようだ。それも、分岐予測を乱すことがあるので、おいそれと
変なコードは吐けない。
0230210NGNG
よく考え直したらもっと簡単に書けるじゃん。
a<bのとき、a%=bはa(変化無し)になるから。

int gcm( int a, int b )
{
 return ( a %= b ) ? gcm( b, a ) : b;
}

って、{}なしで1行に書いてもいいのか?これ。
int gcm( int a, int b ) return ( a %= b ) ? gcm( b, a ) : b;
0231デフォルトの名無しさんNGNG
なんて言語だよ
0232デフォルトの名無しさんNGNG
i:=i+1;
0233デフォルトの名無しさんNGNG
>>232矛盾してる
0234デフォルトの名無しさんNGNG
Pascalの代入演算子苦手だ・・・
0235デフォルトの名無しさんNGNG
>>230
ヲイヲイ・・・一体どんなコンパイラ使っているの?
0236デフォルトの名無しさんNGNG
あのね、2つのディレクトリに別バージョンのファイルがあるとき、
"diff DIR1 DIR2 | grep diff"

ってやると、↓こんなふうに違いのあるファイルだけでてくるの。
> diff DIR1/file1 DIR2/file1
> diff DIR1/file2 DIR2/file2

そんでもってこの結果をコピペして実行すると
ファイルごとのdiffができるの。

・・ちょっと場違いなかきこみだったかな。ゴメンネ。
0237デフォルトの名無しさんNGNG
diff -urN がだめな理由は何ですか?
0238デフォルトの名無しさんNGNG
>>237
NCR の diff コマンドではエラーでした。

>>232

> i := i + 1;

Pascal らしくなら、こうだ。

Inc(i); (* i := i + 1; *)
Inc(i, 5); (* i := i + 5; *)

0239デフォルトの名無しさんNGNG
>>238
diff -crNではどう?
0240デフォルトの名無しさんNGNG
#pragma っておもしろいな
#pragma 的小技おしえれ
0241デフォルトの名無しさんNGNG
>>240
#pragma pack(256)
0242デフォルトの名無しさんNGNG
あげてみます
0243m044249.ap.plala.or.jpNGNG
#define m\
a\
i\
n\
(\
)\
{\
}\
0244m044249.ap.plala.or.jpNGNG
mm

で実行できる
0245m044249.ap.plala.or.jpNGNG
かな
0246デフォルトの名無しさんNGNG
複数の自然数をいくつかの箱にふりわける。その際、各箱に振り分けた数の合計の最大値ができるだけ
小さくなるようにしたい。

例 (10, 2, 6, 9, 3, 11, 5) を4つの箱に入れる場合、

(11) (10, 2) (9, 3) (5, 6)


こういう場合、実際に入れてみる以外に方法はありますか?
0247デフォルトの名無しさんNGNG
>>246
枝切りはいろいろできるだろうけど、最適解が必要なら入れてみるしかないと思うが。
0248デフォルトの名無しさんNGNG
>>16-17
激しくワロタ
0249デフォルトの名無しさんNGNG
>>247
どもです。では、近似値をなるべく早く得るには?としたらどうでしょうか?
0250デフォルトの名無しさんNGNG
>>249
 単純にソートして 大きい方から
 その時点の一番少ない数の箱に入れてゆくというのではダメ?
0251デフォルトの名無しさんNGNG
問題の雰囲気は動的計画法を使うっぽいが、どう使えばよいかは
ワカラン。
0252デフォルトの名無しさんNGNG
>>250
どもです。今、ちょっとした業務用プログラムをそれで動かしているのですが、
たまにうまくいかないことがあります。
要素の個数が約100個、箱が4〜9個、要素の値の範囲が20〜20000というところ
なんですが、力技では無理ですよね。
■ このスレッドは過去ログ倉庫に格納されています