人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

どうプログラムを書けば良いか分からなくなったので質問させてください.
不等間隔のデータの中から,等間隔な部分を抜き出す方法?
例えば,「0 1 3 4 8 9 10 12 14 15」という不等間隔のデータから,等間隔な部分を抜き出すと,「0 4 8 12」,「1 8 15」,「3 9 15」,「4 9 14」,「8 9 10」,「8 12 14」,「9 12 15」がありますが,これをCとかFortranとかで書くとどう書けば良いのでしょう?具体的なソースを教えて頂けたらと思います.また,決まったやり方があるのでしたら教えて下さい.

●質問者: taki
●カテゴリ:コンピュータ 科学・統計資料
✍キーワード:FORTRAN ソース データ プログラム
○ 状態 :終了
└ 回答数 : 6/6件

▽最新の回答へ

1 ● Z9M9Z
●10ポイント
0 1 3 4 8 9 10 12 14 15
+ 1 3 4 8 9 10 12 14 15
- + 2 3 7 8 9 11 13 14
- - + 1 5 6 7 9 11 12
- - - + 4 5 6 8 10 11
- - - - + 1 2 4 6 7
- - - - - + 1 3 5 6
- - - - - - + 2 4 5
- - - - - - - + 2 3
- - - - - - - - + 1

このように全差分をつくって配列にでもおいて、0から順に、同じ差分で2つ以上たどっていけるかをチェックするのはどうでしょう。0から4ずつをたどる例を赤く、1から7ずつをたどる例を青くしてみました。ソースじゃなくてすんませんが。

n個のデータならnの2乗の手間で終わりそう。

例の8 12 14は10 12 14ですね。

◎質問者からの返答

ソースを見てみたいです.


2 ● a3hys
●20ポイント

先頭から順に、間隔を0から順に、2回(3個目に)辿れるかをチェック、とそれぞれループで行う単純なものですが叩き台に・・・。

#include <stdio.h>
void check(int*);
void foo(void);

int dat[16] = { 1,1,0,1,1,0,0,0,1,1,1,0,1,0,1,1 };

void foo(void)
{
int dif; //ループ用(間隔)
int bgn; //ループ用(開始位置)
int cnt; //等間隔のカウント
int i;
int tmp[16];

// 探索開始位置
for (bgn = 0; bgn < 16-2; bgn++) {
// 等間隔の値
for (dif = 1; dif < 16/2; dif++) {
// 計算領域のクリア
for (i=0; i < 16; ++i)
tmp[i] = 0;
cnt = 0;

/////等間隔の存在チェック/////
if (bgn-dif >= 0 &amp;&amp; dat[(bgn-dif)])
continue; //探索済み除外
//探索
i = bgn;
while (1) {
if(i < 16 &amp;&amp; dat[i]) {
tmp[i] = 1;
i += dif;
cnt++;
} else {
break;
}
}
if (cnt>=3) {
// 3個以上の等間隔部分があった場合
check(tmp);
}
}
}
}

void check(int *tmp) //確認用表示
{
int i;
printf("{ ");
for (i=0; i<16; ++i) {
if (tmp[i]) {
printf("%d ", i);
}
}
printf("}\n");
}

int main()
{
foo();

return 0;
}

※行数削減のため、勝手にデータを展開していたり、即値を使ったりしています。

◎質問者からの返答

良い感じです.ありがとうございます.


3 ● siigimaru
●1ポイント

http://always-pg.com/c/runtime_rd/string/strtok.html

http://sometime.minidns.net/~ccgi/autostring.html


C言語ですが、文字分割的なソースを載せます。

◎質問者からの返答

文字分割をどう使うのですか???


4 ● Mook
●60ポイント

>また,決まったやり方があるのでしたら教えて下さい.

プログラムでの「やり方」がアルゴリズムといわれるもので、アルゴリズムしだいで、プログラムの効率が大きく変わります。


初心者はプログラミングとはコードを書くことと思いがちですが、実際はこのアルゴリズムを設計することのほうが重要です。


a3hys さんのコードと似ていますが、データの扱い方が異なっていますので、その違いを見比べてみると面白いかと思います。

ほとんどCでも動くと思いますが、一部 C++ の文法を使用しているので、拡張子をcpp にして実行してください。

(変数の宣言とコメントを修正すれば、C でも動作します。)

#include <stdio.h>

staticvoidcheckSequence( int arCnt, int *arNum );
static int checkNum( int sNum, int *arNum, int cnt );
static void printSequence( int *seqList, int *numCnt );

//------------------------------------------------------
void main( void ) {
//------------------------------------------------------
 int arNum[] = {0, 1, 3, 4, 8, 9, 10, 12, 14, 15 }; // 検索データ : 昇順に定義すること
 checkSequence( sizeof( arNum ) / sizeof(int), arNum );
}

//------------------------------------------------------
staticvoidcheckSequence( int arCnt, int *arNum ) {
//------------------------------------------------------
 int existNum = 0;
 int nextNum;
 int seqList[10];
 
 for( int eqDiff = 1 ; eqDiff<=arNum[arCnt-3] ; eqDiff++ ) { // 等差でループ
 for( int firstNum=0 ; firstNum<eqDiff ; firstNum++ ) { // 初項でループ
 for( nextNum = firstNum ; nextNum<=arNum[arCnt-1] ; nextNum+=eqDiff ) {
 if( checkNum( nextNum, arNum, arCnt ) == 1 )
 seqList[existNum++] = nextNum;
 else
 printSequence( seqList, &existNum );
 }
 printSequence( seqList, &existNum );
 }
 }
 return;
}
//------------------------------------------------------
static int checkNum( int sNum, int *arNum, int cnt ) { // データがあるかをチェック
//------------------------------------------------------
 int i;
 for ( i=0 ; i<cnt ; i++ ) {
 if ( arNum[i] == sNum ) return 1;
 }
 return 0;
}

//------------------------------------------------------
static void printSequence( int *seqList, int *numCnt ) { // データを表示
//------------------------------------------------------
 int i;
 if ( *numCnt >= 3 ) {
 printf("{ ");
 for( i=0 ; i<*numCnt ; i++ ) printf( "%d ", seqList[i] );
 puts("}");
 }
 *numCnt = 0;
}
◎質問者からの返答

ありがとうございます.

勉強になります.


5 ● aside
●60ポイント

あえてjavascript

<html>
<head>
<script language="javascript">
<!--
function calc() {
 // 結果格納用
 var sTemp = "";
 var sResult = "";
 // スペース区切りの値を配列へ変換
 var arrVal = document.getElementById("target").value.split(" ");
 // 配列内の文字列を数値へ変換
 var arrNum = new Array();
 for (var idx=0; idx < arrVal.length; idx++) {
 arrNum[idx] = parseInt(arrVal[idx], 10);
 }
 for (var idx = 0; idx < arrNum.length - 2; idx++) {
 for (var idx0=idx+1; idx0 < arrNum.length - 2; idx0++) {
 // 出力結果初期化
 sTemp = "";
 // 等間隔チェック用の間隔の値
 var iDeff = arrNum[idx0] - arrNum[idx];
 // 比較用値保存
 var iReff = arrNum[idx0];
 // チェック用フラグ
 var flg = false;
 for (var idx1=idx0+1; idx1 < arrNum.length; idx1++) {
 if ((arrNum[idx1] - iReff) == iDeff) {
 // 書き出し一回目は余分に出力する
 if (!flg) {
 flg = true;
 sTemp += arrNum[idx] + " " + arrNum[idx0];
 }
 // 値出力
 sTemp += " " + arrNum[idx1];
 // 比較用値設定
 iReff = arrNum[idx1];
 }
 }
 // 結果出力
 if (flg) {
 if (sResult.indexOf(sTemp) == -1) {
 sResult += sTemp + String.fromCharCode(13);
 }
 }
 }
 }
 document.getElementById("answer").innerText = sResult;
}
//-->
</script>.
</head>
<body>
<input type="text" id="target" style="width:100%;" value="0 1 3 4 8 9 10 12 14 15">
<input type="button" value="計算" onclick="calc()">
<br>
<textarea id="answer" style="width:100%;height:100%;"></textarea>
</body>
</html>
◎質問者からの返答

あえての参戦ありがとうございます.

簡単に書けるもんですね.


1-5件表示/6件
4.前の5件|次5件6.
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ