HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0427
kanamaru自作プログラムの添削15解決


kanamaru

リンク

2015/4/27(Mon) 17:15:25|NO.68802

とあるサイトで以前見かけた問題をプログラムで解きたいと思い、
hspで実装してみようと、試しに作ってみた所、if文が複雑になってしまい、
もっとわかりやすく書けないかと思い質問しました。
その問題とは
「与えられた3点を頂点とする三角形が点対称か線対称かそれ以外か調べよ」
という問題です。
この問題を次のように考えました。
点対称…三辺が等しい
線対称…二辺が等しい
よって次のように組みました。
点対称は2、線対称は1、それ以外は0が返る関数として作られています。

#module #defcfunc check int x1,int y1,int x2,int y2,int x3,int y3 if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)=(x2-x3)*(x2-x3)+(y2-y3)*(y2-y3)=(x3-x1)*(x3-x1)+(y3-y1)*(y3-y1))and((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3))and((x3-x1)*(x3-x1)+(y3-y1)*(y3-y1)=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) { return 2 } if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)=(x2-x3)*(x2-x3)+(y2-y3)*(y2-y3)=(x3-x1)*(x3-x1)+(y3-y1)*(y3-y1))or((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3))or((x3-x1)*(x3-x1)+(y3-y1)*(y3-y1)=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) { return 1 } return 0 #global
もちろん、andやorでつなげているところを3重if文にすれば少しは見やすいと思いますが、
それ以外に簡単に実装する方法はありますか?



この記事に返信する


kanamaru

リンク

2015/4/27(Mon) 17:29:58|NO.68803

少しマクロを用いた所、少し簡単に実装できたので報告します。

#module #define ctype kyori2(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4) #defcfunc check int x1,int y1,int x2,int y2,int x3,int y3 if (kyori2(x1,y1,x2,y2),kyori2(x2,y2,x3,y3))and(kyori2(x2,y2,x3,y3)=kyori2(x3,y3,x1,y1))and(kyori2(x3,y3,x1,y1)=kyori2(x1,y1,x2,y2)) { return 2 } if (kyori2(x1,y1,x2,y2)=kyori2(x2,y2,x3,y3))or(kyori2(x2,y2,x3,y3)=kyori2(x3,y3,x1,y1))or(kyori2(x3,y3,x1,y1)=kyori2(x1,y1,x2,y2) { return 1 } return 0 #global
よりわかりやすく実装できるように知恵を貸してください。



kanamaru

リンク

2015/4/27(Mon) 17:31:40|NO.68804

一か所=となるべき場所を,にしてたようですいませんでした



kanamaru

リンク

2015/4/27(Mon) 18:00:43|NO.68805

強引ですが、これって大丈夫ですか

#module #define ctype kyori2(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4) #defcfunc check int x1,int y1,int x2,int y2,int x3,int y3 if1=(kyori2(x1,y1,x2,y2)=kyori2(x2,y2,x3,y3)) if2=(kyori2(x2,y2,x3,y3)=kyori2(x3,y3,x1,y1)) if3=(kyori2(x3,y3,x1,y1)=kyori2(x1,y1,x2,y2)) if (if1)and(if2)and(if3) { return 2 } if (if1)or(if2)or(if3) { return 1 } return 0 #global
実は、hspでもbooleanに似たようなことができるので、それを使ってみました。



kanamaru

リンク

2015/4/27(Mon) 18:13:26|NO.68806

動作上不具合が生じたので、
少し書き換えました。

#module #define ctype kyori2(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4) #define if1 (kyori2(x1,y1,x2,y2)=kyori2(x2,y2,x3,y3)) #define if2 (kyori2(x2,y2,x3,y3)=kyori2(x3,y3,x1,y1)) #define if3 (kyori2(x3,y3,x1,y1)=kyori2(x1,y1,x2,y2)) #defcfunc check int x1,int y1,int x2,int y2,int x3,int y3 if (if1)and(if2)and(if3) { return 2 } if (if1)or(if2)or(if3) { return 1 } return 0 #global
より良いプログラムになるようにアドバイスをよろしくお願いします。



FunnyMaker

リンク

2015/4/27(Mon) 18:35:02|NO.68807

先ほどちょくちょく書き込んでたものを修正してこんな感じに。


#module #defcfunc check int x1,int y1,int x2,int y2,int x3,int y3 #define ctype d(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4) A = d(x1,y1,x2,y2) : B = d(x2,21,x3,y3) : C = d(x3,y3,x1,y1) return (A=B&B=C&C=A) | (A=B|B=C|C=A) #global

三角形が点対称なら自ずと線対称でしたね。



FunnyMaker

リンク

2015/4/27(Mon) 18:40:10|NO.68808

↑のミスを修正しました。


#module #define ctype d(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4) #defcfunc check int x1,int y1,int x2,int y2,int x3,int y3 A = d(x1,y1,x2,y2) : B = d(x2,y2,x3,y3) : C = d(x3,y3,x1,y1) return (A=B&B=C&C=A) + (A=B|B=C|C=A) #global



kanamaru

リンク

2015/4/27(Mon) 18:48:10|NO.68809

なるほど、そのように記述することもできるんですね。
勉強になりました。
ありがとうございます。



774

リンク

2015/4/27(Mon) 19:03:47|NO.68810

見当違いや勘違いかも知れませんが、「点対称の三角形」というのは成立するのでしょうか…(線分?)



FunnyMaker

リンク

2015/4/27(Mon) 19:16:08|NO.68812

>774さん

言われてみればその通りですね。(何も気にせずに回答してた自分に(笑))
点対称はπrad回転で元の図形に一致することですから、三角形ではあり得ませんね。
その問題の載っていたサイトを見てみたいものです。



掘木

リンク

2015/4/28(Tue) 13:00:26|NO.68824

気になった点をいくつか。

1.引数がintである以上の情報なしに差、積をしていませんか?
(値の範囲から、オーバーフローが起きないことを確かめていますか?
2.与えられる三点が本当に三角形を形成できるかどうか判別しなくて良いのでしょうか?
(直線上に並ぶのを認める場合、大きく解釈が変わります。
3.与えられる頂点は整数上の座標を持ちます。このとき、正三角形を形成可能ですか?
不可能なら、そもそも判別する必要がなくすっきりします。

FunnyMakerさんと同じく問題を見てみたいですね、



kanamaru

リンク

2015/4/28(Tue) 17:33:07|NO.68829

確かに点対称ってそういう意味でしたね…。
のっていたサイトはcodeIQと記憶しています。
ひょっとしたら何か思い違いをしているかもしれません。
値の範囲のチェックや三角形が成立するかどうかを調べるひつようがありましたね
確かに整数の範囲だと正三角形ができないのでdoubleにします。
FunnyMakerさんのプログラムをもとにして、
自分なりに改造してみました。
#module
#define ctype d(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4)
#defcfunc check double x1,double y1,double x2,double y2,double x3,double y3
A = d(x1,y1,x2,y2) : B = d(x2,y2,x3,y3) : C = d(x3,y3,x1,y1)
return (A+B>C)*(B+C>A)*(A+C>B)*((A=B&B=C&C=A) + (A=B|B=C|C=A))
#global
前と同じく添削お願いします。
あとオーバーフローにならないかというのはどのように実装すれば
いいのでしょうか?
オーバーフローというのが値が大きくなりすぎることだというのは
理解しています。



kanamaru

リンク

2015/4/28(Tue) 17:59:04|NO.68831

不等号の向きを5行目で間違えました。
正しくは、
return (A+B<C)*(B+C<A)*(A+C<B)*((A=B&B=C&C=A) + (A=B|B=C|C=A))
です。



FunnyMaker

リンク

2015/4/28(Tue) 18:17:33|NO.68833

オーバーフローもそうですけど、丸め誤差も気になります。(この辺は計算機システムに詳しい人に譲るとして...)

ここからは正味どうでもいい話になりますが、
>整数の範囲だと正三角形ができないのでdoubleにします。
これ、今更思ったのですけどdoubleにしたところで依然として意味ないですね。
doubleといえども所詮は有限小数。
そして3点すべてが有理点であるような正三角形は存在しません(容易に証明できます)。
故に正三角形であるかどうかのチェックは不要です。


↑のことはひとまず置いておくとして...
も、

>return (A+B>C)*(B+C>A)*(A+C>B)*((A=B&B=C&C=A) + (A=B|B=C|C=A))
No.68808で私が一例として載せた方法と本質的には同じですね。
これはこれでいいと思うんですけど、
短く記述した代償として無駄な計算を行ってしまうリスクがつきまといます。

「何を目指すのか?」でやるべきことは変わってきます。
無駄な計算をなるべく減らしたいのであれば、こんなのもありますかね。

if absf(A-B) < C & C < A+B { if A=B&B=C&C=A { return 2 } else { return A=B|B=C|C=A } } else : return 0
(※正三角形の存在云々は考慮していません)



kanamaru

リンク

2015/4/28(Tue) 18:53:30|NO.68837

どうせなら機能を増やせるだけ増やそうと機能を増やしてみました。
といっても正三角形の処理は消したので実質機能は増えてないと思いますが
リスクが生じるのは薄々気づいてはいたのですがやっぱり生じるんですね。
リスクについては考えずに機能を付け足しました。

/* 二等辺三角形…1 直角三角形…2 直角二等辺三角形…3 それ以外…0 */ #module #define ctype d(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4) #defcfunc check double x1,double y1,double x2,double y2,double x3,double y3 A = d(x1,y1,x2,y2) : B = d(x2,y2,x3,y3) : C = d(x3,y3,x1,y1) return (A+B<C)*(B+C<A)*(A+C<B)*((A=B|B=C|C=A)+(A*A+B*B=C*C|B*B+C*C=A*A|C*C+A*A=B*B)+((A=B|B=C|C=A)&(A*A+B*B=C*C|B*B+C*C=A*A|C*C+A*A=B*B))) #global
returnらへんを整理する必要がありますね
添削お願いします。
こうすればリスクがなくなるというアイデアをくれる方いましたら
スクリプトの修正をお願いします。



kanamaru

リンク

2015/4/28(Tue) 18:59:54|NO.68838

return文を整理してみました。
前と同じくリスクは考えていません。

/* 二等辺三角形…1 直角三角形…2 直角二等辺三角形…3 それ以外…0 */ #module #define ctype d(%1,%2,%3,%4) (%1-%3)*(%1-%3)+(%2-%4)*(%2-%4) #defcfunc check double x1,double y1,double x2,double y2,double x3,double y3 A = d(x1,y1,x2,y2) : B = d(x2,y2,x3,y3) : C = d(x3,y3,x1,y1) nitouhen = (A=B|B=C|C=A) : tyokkaku = (A*A+B*B=C*C|B*B+C*C=A*A|C*C+A*A=B*B) return (A+B<C)*(B+C<A)*(A+C<B)*(nitouhen+tyokkaku+(nitouhen&tyokkaku)) #global
添削お願いします。



ONION software Copyright 1997-2023(c) All rights reserved.