座標比較

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
しゅう

座標比較

#1

投稿記事 by しゅう » 18年前

ご無沙汰してます。また詰まっちゃいましたんでおねがいします。
テキストファイル(中身は三次元の座標が書いてあります)を比較して何%合ってるかって言うプログラムを作りたいです。
どうすればいいかお願いします。

box

Re:座標比較

#2

投稿記事 by box » 18年前

> 何%合ってるか

合致度を求めるロジック(計算式)は明確になっていますか?

管理人

Re:座標比較

#3

投稿記事 by 管理人 » 18年前

2つのファイルからデータを読み取って比較するのでしょうか?

三次元の座標が書いてあるとは主にどんな座標で、どのようなフォーマットすか?

(0,3,4),(2,6,3),(3,6,4)...とか書いてあるんでしょうか?

しゅう

Re:座標比較

#4

投稿記事 by しゅう » 18年前

ちょっと変更です。
えと何%合ってるかどうかではなく、幾つ一致したかに変わりました。
なのでロジックは引くだけで大丈夫かな?と思っています。
座標は
1,3,2
2,1,4

 ・
 ・

て感じで書かれています。

keichan

Re:座標比較

#5

投稿記事 by keichan » 18年前

ファイルに何万もの座標がないのであれば
一旦変数に全部座標を読み込んで、比較を行う方法が楽そうです。

しゅう

Re:座標比較

#6

投稿記事 by しゅう » 18年前

座標は3万ほど有ります

管理人

Re:座標比較

#7

投稿記事 by 管理人 » 18年前

遅くなりました。

えっと、仕様を明確にしていいですか?

1,2,3
4,2,4
6,2,4
3,7,4
1,2,3
6,3,5
4,2,4
1,2,3

このような3次元データがあるとします。
8個のデータのうち、1,2,3は3つ重複していました。
4,2,4は2つ重複していました。

このようにこれが何個って言わないといけないのでしょうか?
それとも一致した座標の個数だけでよく、重複回数は必要ないのでしょうか?

管理人

Re:座標比較

#8

投稿記事 by 管理人 » 18年前

重複した座標の個数だけでしたら以下で計算できると思います。
#include <stdio.h>

#define N 10 

typedef struct{
	int x,y,z;
}zahyou_t;

int main(){
	int count=0,on;
	int onoff[N]={};
	zahyou_t num[N]={{1,2,3},
		        {2,2,3},
		        {3,2,3},
		        {4,2,3},
		        {5,2,3},
		        {6,2,3},
		        {6,2,3},
		        {1,2,3},
		        {1,2,3},
		        {2,2,3}};
	for(int i=0;i<N;i++){
		if(onoff==1)
			continue;
		on=0;
		for(int j=0;j<N;j++){
			if(i==j)
				continue;
			if(num.x==num[j].x && num.y==num[j].y && num.z==num[j].z){
				onoff[j]=1;
				on=1;
			}
		}
		if(on==1 && onoff==0)
			count++;
	}
	printf("一致する座標は%d個\n",count);
	return 0;
}

しゅう

Re:座標比較

#9

投稿記事 by しゅう » 18年前

えっと例えば
Aのデータが
1,2,3
1,3,3
2,1,2
2,2,3
3,2,3
3,3,1

Bのデータが
1,1,2
1,2,3
1,3,3
2,1,2
2,2,3
3,2,3


だとしたとき
AとBを比較して一致しない座標が
1,1,2
2,1,2
3,3,1
なので一致しない座標は3個ですみたいにしたいんです。


それで引いて絶対値が1になる部分をカウントしていけばいいかなと思ったんですが、この場合どのような感じになるでしょうか?

box

Re:座標比較

#10

投稿記事 by box » 18年前

> AとBを比較して一致しない座標が
> 1,1,2
> 2,1,2
> 3,3,1
> なので一致しない座標は3個ですみたいにしたいんです。

2,1,2
はAにもBにもありますが、「一致しない」と判断するのですか?
一致するかしないかの判断基準がよくわかりません。

しゅう

Re:座標比較

#11

投稿記事 by しゅう » 18年前

>2,1,2
>はAにもBにもありますが、「一致しない」と判断するのですか?

すいません見間違って余計な物まで書いただけです。

box

Re:座標比較

#12

投稿記事 by box » 18年前

AとBの並び順は
・第一キー:X座標の昇順
・第二キー:Y座標の昇順
・第三キー:Z座標の昇順
であることが保証されていますか?

もし保証されていなければ、座標比較の前にソートのロジックを
組み込んでおく必要がありそうです。

管理人

Re:座標比較

#13

投稿記事 by 管理人 » 18年前

↑クリックで画像拡大↑

とりあえず出来ました。
こんな感じでしょうか?
num1とnum2に3次元の座標があり、そのうちnum1のxをソートして比較しています。
詳しい内容は次の投稿の注釈をご覧下さい。

なお、データが3万ということなんでクイックソートを用いました。
クイックソートの説明は私のHPの別ページで詳しく書いていますのでご覧下さい。
#include  <stdio.h>

#define N 10 

typedef struct{
	int x,y,z;
}zahyou_t;


void change(int i,int j, zahyou_t num[ ]){//配列要素i番目とj番目の値を入れ替える
	int t;
	t=num.x;	num.x=num[j].x;	num[j].x=t;
	t=num.y;	num.y=num[j].y;	num[j].y=t;
	t=num.z;	num.z=num[j].z;	num[j].z=t;
}

void sort(int l, int r, zahyou_t num[ ]){//lを一番左端の配列要素、rを一番右端の要素としてソートする。
	int i,j,p;
	i=l;j=r;
	p=num[(l+r)/2].x;
	while(1) {
		while(num.x<p){//左からピボット以上を探索
			i++;
		}
		while(p<num[j].x){//右からピボット以下を探索
			j--;
		}
		if(i>=j){//探索地点がぶつかったら終了
			break;
                }
                change(i,j,num);//お互い発見した値をいれかえる
		i++;
		j--;
	}

	if(l<i-1){//左範囲が分割可能なら
                sort(l,i-1,num);//左範囲を分割してソートを行う
	}
	if(j+1<r){//右範囲が分割可能なら
                sort(j+1,r,num);//右範囲を分割してソートを行う
	}
}

int main(void){
	zahyou_t num1[N]=
	{{1,2,3},
	 {3,8,4},
	 {7,7,9},
	 {4,1,5},
	 {5,1,3},
	 {1,2,3},
	 {6,4,6},
	 {3,1,4},
	 {6,2,2},
     {3,1,4}};
	zahyou_t num2[N]=
	{{7,2,3},
	 {1,2,3},
	 {1,2,3},
	 {6,4,6},
	 {5,1,5},
	 {3,1,4},
	 {3,2,3},
	 {6,2,2},
	 {1,2,3},
     {3,1,4}};
	int count=0,on;
	int onoff[N]={};
	int x=-1,y=-1,z=-1;//存在しない座標をセット

	printf("num1ソート作業前\n");
	for(int i=0;i<N;i++)
		printf("%d %d %d\n",num1.x,num1.y,num1.z);

	sort(0, N-1, num1);

	printf("num1ソート作業後\n");
	for(int i=0;i<N;i++)
		printf("%d %d %d\n",num1[i].x,num1[i].y,num1[i].z);
	printf("num2\n");
	for(int i=0;i<N;i++)
		printf("%d %d %d\n",num2[i].x,num2[i].y,num2[i].z);

	for(int i=0;i<N;i++){
		if(num1[i].x==x && num1[i].y==y && num1[i].z==z)
			continue;
		on=0;
		for(int j=0;j<N;j++){
			if(num1[i].x==num2[j].x && num1[i].y==num2[j].y && num1[i].z==num2[j].z){
				on=1;
				printf("num1[%d]とnum2[%d]が一致\n",i,j);
				break;
			}
		}
		if(on==1)
			count++;
		x=num1[i].x;	y=num1[i].y;	z=num1[i].z;
	}
	printf("一致したのは%d個\n",count);
	return 0;
}

管理人

Re:座標比較

#14

投稿記事 by 管理人 » 18年前

最初のprintfは表示をおこなっているだけですので、後半をご覧下さい。

何かわからないところがあったらまた聞いてください。
int main(void){
	zahyou_t num1[N]=
	{{1,2,3},
	 {3,8,4},
	 {7,7,9},
	 {4,1,5},
	 {5,1,3},
	 {1,2,3},
	 {6,4,6},
	 {3,1,4},
	 {6,2,2},
     {3,1,4}};
	zahyou_t num2[N]=
	{{7,2,3},
	 {1,2,3},
	 {1,2,3},
	 {6,4,6},
	 {5,1,5},
	 {3,1,4},
	 {3,2,3},
	 {6,2,2},
	 {1,2,3},
     {3,1,4}};
	int count=0,on;
	int onoff[N]={};
	int x=-1,y=-1,z=-1;//存在しない座標をセット

	printf("num1ソート作業前\n");
	for(int i=0;i<N;i++)
		printf("%d %d %d\n",num1.x,num1.y,num1.z);

	sort(0, N-1, num1);

	printf("num1ソート作業後\n");
	for(int i=0;i<N;i++)
		printf("%d %d %d\n",num1.x,num1.y,num1.z);
	printf("num2\n");
	for(int i=0;i<N;i++)
		printf("%d %d %d\n",num2.x,num2.y,num2.z);

	for(int i=0;i<N;i++){
		//前の座標をx,y,zに格納しておき、前のと同じだったらカウントしない。
		if(num1.x==x && num1[i].y==y && num1[i].z==z)
			continue;
		on=0;//forで回った後、今回の比較で一致したものがあったかどうかを示す。
		for(int j=0;j<N;j++){
			if(num1[i].x==num2[j].x && num1[i].y==num2[j].y && num1[i].z==num2[j].z){//比較
				on=1;
				printf("num1[%d]とnum2[%d]が一致\n",i,j);
				break;
			}
		}
		if(on==1)//一致したものがあったらカウント
			count++;
		x=num1[i].x;	y=num1[i].y;	z=num1[i].z;//今回の座標を次の比較で使うため、記憶
	}
	printf("一致したのは%d個\n",count);
	return 0;
}

しゅう

Re:座標比較

#15

投稿記事 by しゅう » 18年前

一致した物ではなく一致しなかった物を出したいんでonが0のときカウントするようにしたんですが、これではAにあってBにない時はカウントされますがAになくてBにある場合はカウントされないんですがどこを弄ればいいでしょうか?
あと座標のある部分を1、ない部分を0と考えて絶対値A-Bで1になった部分を数えるようにしようって言うのは間違ってて無理なんでしょうか?(うまく作れてなかったですがそういう風に考えていたので管理人さんの考え方を見てそういうのもあるんだと感心してしまいました)

フリオ

Re:座標比較

#16

投稿記事 by フリオ » 18年前

 
 こんな感じでどうでしょう。
#include <stdio.h>
#include <stdlib.h>

void DataError(int flag)
{
    char *message[/url] = {"File Open Error", "Data Empty",};
    
    puts(message[flag + 1]);
    exit(1);
}

int ReadData(int data[/url][10][10][10], char *fname[/url])
{
    FILE *fp;
    int y, x, z, i, j;
    
    for(j = 0; j < 2; j ++){
        if((fp = fopen(fname[j + 1], "r")) == NULL) return -1;
        for(i = 0; fscanf(fp, "%d,%d,%d", &x, &y, &z) != EOF; i ++){
            data[j][y][x][z] |= 1;
        }
        fclose(fp);
    }
    return i;
}

int CompData(int result[/url][10][10], int data[/url][10][10][10])
{
    int y, x, z, count;
    
    for(count = y = 0; y < 10; y ++){
        for(x = 0; x < 10; x ++){
            for(z = 0; z < 10; z ++){
                result[y][x][z] = data[0][y][x][z] ^ data[1][y][x][z];
                count += result[y][x][z];
            }
        }
    }
    return count;
}

void PrintResult(int result[/url][10][10], int count)
{
    int y, x, z;
    
    for(y = 0; y < 10; y ++){
        for(x = 0; x < 10; x ++){
            for(z = 0; z < 10; z ++){
                if(result[y][x][z]) printf("(%d,%d,%d)\n", x, y, z);
            }
        }
    }
    printf("Different %d\n", count);
    return;
}

int main(int argc, char *argv[/url])
{
    int result[10][10][10] = {0,};
    int data[2][10][10][10] = {0,};
    int count, flag;
    
    if(argc != 3){
        puts("Parameter Error");
        return 1;
    }
    if((flag = ReadData(data, argv)) < 1) DataError(flag);
    count = CompData(result, data);
    PrintResult(result, count);
    return 0;
}

フリオ

Re:座標比較

#17

投稿記事 by フリオ » 18年前

 
 配列をひとつにしました。
#include <stdio.h>
#include <stdlib.h>

void DataError(int flag)
{
    char *message[/url] = {"File Open Error", "Data Empty",};
    
    puts(message[flag + 1]);
    exit(1);
}

int ReadData(int data[10][10][10], char *fname[/url])
{
    FILE *fp;
    int y, x, z, i, j;
    
    for(j = 1; j <= 2; j ++){
        if((fp = fopen(fname[j], "r")) == NULL) return -1;
        for(i = 0; fscanf(fp, "%d,%d,%d", &x, &y, &z) != EOF; i ++){
            data[y][x][z] ++;
        }
        fclose(fp);
    }
    return i;
}

int ProcessData(int data[10][10][10])
{
    int y, x, z, count;
    
    for(count = y = 0; y < 10; y ++){
        for(x = 0; x < 10; x ++){
            for(z = 0; z < 10; z ++){
                data[y][x][z] &= 1;
                count += data[y][x][z];
            }
        }
    }
    return count;
}

void PrintResult(int data[10][10][10], int count)
{
    int y, x, z;
    
    for(y = 0; y < 10; y ++){
        for(x = 0; x < 10; x ++){
            for(z = 0; z < 10; z ++){
                if(data[y][x][z]) printf("(%d,%d,%d)\n", x, y, z);
            }
        }
    }
    printf("Different %d\n", count);
    return;
}

int main(int argc, char *argv[/url])
{
    int data[10][10][10] = {0,};
    int count, flag;
    
    if(argc != 3){
        puts("Parameter Error");
        return 1;
    }
    if((flag = ReadData(data, argv)) < 1) DataError(flag);
    count = ProcessData(data);
    PrintResult(data, count);
    return 0;
}

管理人

Re:座標比較

#18

投稿記事 by 管理人 » 18年前

単に個数がほしいのでしたら
全部の個数 - count
でいいのではないでしょうか?

フリオ

Re:座標比較

#19

投稿記事 by フリオ » 18年前

 
 ごめんなさい。
配列が一つのほうは間違ってます。
これだと、同じファイルにデータの重複があると、
正しい結果が出ません。
 

しゅう

Re:座標比較

#20

投稿記事 by しゅう » 18年前

載せて下さったソースを参考に何とか完成しましたどうもです。

閉鎖

“C言語何でも質問掲示板” へ戻る