1

ユリウス暦やグレゴリオ暦など、日付を検証するための式を作成する必要がある、この非常識な宿題があります...

問題は、それがすべて1つの式に含まれている必要があるため、どの式も使用できないことです。;

式で変数を定義するオプションはありますか?何かのようなもの

d < 31 && (bool leapyear = y % 4 == 0) || (leapyear ? d % 2 : 3) ....

ここで、1つ以上の変数を定義して初期化し、それらを1つの式で使用せずに使用でき;ますか?

編集:それは1行の表現でなければならないと明確に言われています。機能なし..

今のやり方はマクロを書いて展開することなので、こういうものになってしまいます

#define isJulian(d, m, y) (y < 1751 || (y == 1752 && (m < 9) || (m == 9 && d <= 2)))
#define isJulianLoopYear(y) (y % 4 == 0)
#define isGregorian(d, m, y) (y > 1573 || (y == 1752 && (m > 9) || (m == 9 && d > 13)))
#define isGregorianLoopYear(y) ((y % 4 == 0) || (y % 400 = 0))
// etc etc ....

これが問題を解決するための唯一の適切な方法のように見えます

編集:これが元の質問です

変数がd mありy、日、月、年が含まれているとします。タスクは、日付が有効かどうかを決定する単一の式を作成することです。日付が有効な場合は値がtrue(ゼロ以外の値)であり、日付が無効な場合はfalse(ゼロ)である必要があります。

これは式の例です(正しい式は次のようになります):

d + 4 == y ^ 85 ? ~m : d * (y-2)

これらは間違った答えの例です(表現ではありません):

if ( log ( d ) == 1752 ) m = 1;

また:

for ( i = 0; i < 32; i ++ ) m = m / 2;

最後に1つの式のみを含むファイルのみを送信;してください。コマンドやプログラム全体を送信しないでください。

  • 2.9.1752がユリウス暦になるまで、その後はグレゴリオ暦になります
  • ユリウス暦では、毎年うるう年で4で割ることができます。
  • グレゴリオ暦では、うるう年であり、4で割り切れるが、100で割り切れるわけではありません。400で割り切れる年は別の例外であり、うるう年です。
  • 1800、1801、1802、1803、1805、1806、....、1899、1900、1901、...、2100、...、2200はループ年ではありません。
  • 1896、1904、1908、...、1996、2000、2004、...、2396、...、2396、2400はループ年です
  • 1752年9月には、2.9.1752の後に14.9.1752が続く場合の別の例外であるため、日付3.9.1752、4.9.1752、...、13.9.1752は無効です。
4

9 に答える 9

6
((m >0)&&(m<13)&&(d>0)&&(d<32)&&(y!=0)&&(((d==31)&&
((m==1)||(m==3)||(m==5)||(m==7)||(m==8)||(m==10)||(m==12)))
||((d<31)&&((m!=2)||(d<29)))||((d==29)&&(m==2)&&((y<=1752)?((y%4)==0):
((((y%4)==0)&&((y%100)!=0))
||((y%400)==0)))))&&(((y==1752)&&(m==9))?((d<3)||(d>13)):true))
于 2009-10-03T04:32:39.583 に答える
5

<evil> 既存のものを再利用できるのに、なぜ新しいものを定義するのですか?errno完全な一時変数です。 </evil>

于 2009-10-05T10:43:19.740 に答える
4

宿題の目的は、変数を使わずにこれを行うように依頼することであり、あなたがやろうとしていることはその目的を損なう可能性があると思います。

于 2009-10-02T22:59:28.800 に答える
3

標準のC++では、これは不可能です。G ++には、それを実行できるステートメント式と呼ばれる拡張機能があります。

于 2009-10-02T22:52:32.100 に答える
2

私はあなたができるとは思いませんが、あなたができたとしても、それはそれらが定義されている括弧の内側にのみスコープを持ち(あなたの例では)、それらの外側で使用することはできません。

于 2009-10-02T22:52:50.693 に答える
1

私があなたに完全に提供しないあなたの解決策は、おそらくこれらの線に沿っているでしょう:

isJulian ? isJulianLeapyear : isGregorianLeapyear

具体的には、次のようになります。

isJulian ? (year % 4) == 0 : ((year % 4) == 0 || (year % 400) == 0) 

アルゴリズムが正しいことを確認する必要があります。私はカレンダーの専門家ではないので、それについては知りません。

于 2009-10-03T02:45:20.160 に答える
1

最初に:しないでください。かわいいかもしれませんが、それを可能にする拡張機能があったとしても、コードゴルフは危険なゲームであり、ほとんどの場合、解決するよりも多くの悲しみを引き起こします。

さて、宿題で定義された「本当の」質問に戻りましょう。追加機能を作成できますか?その場合、それがうるう年であるかどうかを変数で取得する代わりに、正しい値を返す関数isLeapYear(int year)を作成します。

はい、それはあなたがそれを複数回計算することを意味します。それがパフォーマンスの問題になるとしたら、私は信じられないほど驚かれることでしょう...そしてそもそもそれを心配するのは時期尚早の最適化です。

これを行う一環として関数を書くことが許可されていなかったら、私は非常に驚きます。それはこのような演習の半分のポイントになるようです。

.....。

さて、これがあなたがする必要があることの簡単な概要です。

まず、基本的な検証-その月、日、年はすべて可能な値です-月0-11(0ベースと仮定)、日0-30、年は非負(それが制約であると仮定)。

あなたがそれを過ぎたら、私はおそらく1752年の特別なケースをチェックするでしょう。

それが関係ない場合は、「通常の」月は非常に簡単に処理できます。

これにより、うるう年のケースが残ります。これは、うるう年であるかどうか(グレゴリオ暦/ジュリアンに基づいてさらに分類されます)と、その時点で日付が有効かどうかという2つの表現に分けることができます。

したがって、最高レベルでは、式は次のようになります。

areWithinRange(d、m、y)&& pass1752SpecialCases(d、m、y)&& pass30DayMonths(d、m、y)&& pass31DayMonths(d、m、y)&& passFebruaryChecks(d、m、y)

ルール違反をアクティブに検出した場合にのみ部分式からfalseを返すと仮定すると(30DayMonthルールの6月の31日はfalseを返しますが、2月の30日は無関係であるため、trueを渡します)、ほとんど可能です。そのレベルの論理は正しいと言います。

この時点で、個々の部分に個別の関数を記述します(純粋な式として、単一のreturn ...ステートメントとして)。それらを配置したら、最上位の式のメソッド呼び出しを拡張バージョンに置き換えることができます。すべてを十分に括弧で囲んでください(それは単語ですか?)。

また、式を使用し、有効な入力と無効な入力が多数あるテストハーネスプログラムを作成し、正しいことを行っていることを確認します。次のような操作を行うことで、最終的なターンインのカットアンドペーストを簡単にする関数でそれを記述できます。

bool isValidDate(int d, int m, int y)
{
    return
        // your expression here
}

式はそれ自体で1行になるため、切り取りと貼り付けが簡単になります。

ロジックを単純化する他の方法を見つけることができます。たとえば、1752の特殊なケースを除いて、1〜28日は常に有効です。

于 2009-10-03T01:20:45.737 に答える
0

宿題であることを考えると、自分で解決策を導き出すためのアプローチが一番だと思います。

私がこの課題に取り組んでいるとしたら、私はルールを破ることから始めます。

  1. 変数d、m、およびyを指定して、日付の有効性に関するブール結果を返すc++関数を記述します。私は必要な数の非再帰的なヘルパー関数を使用し、if、else if、elseを自由に使用しますが、ループは発生しません。

  2. 次に、すべてのヘルパー関数をインライン化します

  3. 私はすべてのif、else if、elseステートメントを?:表記

変数の使用を制限することに成功した場合、これをすべて変数のない単一の関数に減らすことができるかもしれません。その本体には、私が求める単一の式が含まれます。

幸運を。

于 2009-10-03T03:00:11.080 に答える
0

どういうわけか、明らかに日付を渡す必要があります。それを超えて、あなたが実際にやろうとしているのは連鎖&&||(構造体として日付を取得すると仮定してtm):

#include <ctime>
bool validate(tm date)
{
     return (
             // sanity check that all values are positive
             date.tm_mday >= 1 && date.tm_mon >= 0 && date.tm_year >= 0
             // check for valid days
             && ((date.tm_mon == 0 && date.tm_mday <= 31)
              || (date.tm_mon == 1 && date.tm_mday <= (date.tm_year % 4 ? 28 : 29))
              || (date.tm_mon == 2 && date.tm_mday <= 31)
             // yadda yadda for the other months
              || (date.tm_mon == 11 && date.tm_mday <= 31))
             );
}

実際には括弧date.tm_year % 4 ? 28 : 29は必要ありませんが、読みやすくするために括弧を含めています。


アップデート

コメントを見ると、グレゴリオ暦に存在しない日付を検証するための同様のルールも必要になります。

更新II

過去の日付を扱っているため、より正確なうるう年テストを実装する必要があります。ただし、私は通常、将来の日付を扱います。この誤ったうるう年のテストでは、2012、2016、2020、2024、2028、2032、2036、2040、2044、2048、2052、2056、2060、2064、 2068、2072、2076、2080、2084、2088、2092、および2096。このテストが2100で失敗する前に、シリコンベースのコンピューターは遺物を忘れてしまうと予測します。当時使用されていた量子コンピューターでC++を使用するのではないかと真剣に疑っています。その上、私はバグを修正するために割り当てられたプログラマーではありません。

于 2009-10-03T00:25:17.837 に答える