2009-10-02 2 views
1

나는 율리우스 력과 그레고리력 및 다른 많은 것들과 관련하여 날짜를 검증하는 표현식을 만들어야하는 미친 숙제를 가지고있다 ...C++에서 표현식에 변수를 정의 할 수 있습니까?

문제는 그것이 모두 하나의 표현식이어야한다는 것이다. 임의로 사용하지 마십시오 ;

variable in expression을 정의 할 수있는 옵션이 있습니까? 내가 정의하고 하나 개 이상의 변수를 초기화하고 ;를 사용하지 않고 하나 개 표현에서 사용할 수

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

같은 뭔가?

편집 : 명시 적으로 한 줄로 된 표현식이어야합니다. 어떤 기능이 없습니다 ..

이이를 해결하는 유일한 적합한 방법입니다처럼이

#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 .... 

같은 물건을 끝낸다 내가 지금 그것을하고 있어요 매크로를 작성하고이를 확대 방법, 이렇게 본다 문제

편집 : 여기에 원래의 질문을하다

한다고 가정 우리가 일, 월 및 연도를 포함하는 변수 dmy 있습니다. 작업은 날짜가 유효한지 여부를 결정하는 하나의 단일 표현식을 작성하는 것입니다. 날짜가 유효하면 값은 true (0이 아닌 값)이고 날짜가 유효하지 않으면 false (0) 여야합니다.

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

나 :

이 잘못 답변의 예 (안 표현)이다

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

을 :

는 (정확한 표현은 다음과 같이 보일 것이다) 표현의 예입니다
for (i = 0; i < 32; i ++) m = m/2; 

;없이 하나의 표현식 만 포함 된 파일 만 제출 끝. 명령이나 전체 프로그램을 제출하지 마십시오. 그 날짜가 율리우스 력에서 그레고리력

  • 4 윤년으로 매년 분할 가능한입니다 후 1752년 2월 9일까지

    • 는 율리우스 력이었다.
    • 그레고리오 (Gregorian) 달력은 어느 해보다 도약 연도는 4로 나눌 수 있지만 100으로 나눌 수는 없습니다. 400으로 나눌 수있는 연도는 또 다른 예외이며 윤년입니다.
    • 1800, 1801, 1802, 1803, 1805, 1806, ..., 1899, 1900, 1901, ..., 2100, ..., 2200은 루프 연가가 아닙니다. 1752년 2월 9일이 때
    • 9 월 1752
    • 또 다른 예외는
    • 1896, 1904, 1908, ..., 1996, 2000, 2004, ..., 2396, ..., 2396, 2400 루프 년 있습니다 14.9.1752 다음에 3.9.1752, 4.9.1752, ..., 13.9.1752는 유효하지 않습니다.
  • +0

    매크로를 사용하고 사전 처리 된 표현식을 제출 하시겠습니까? 또한 윤년 규칙은 그보다 더 복잡합니다. 그런데이 숙제의 핵심은 무엇일까? 표현이 아닌 함수가 아니라고 확신합니까? – UncleBens

    +0

    윤년 규칙은 좀 더 복잡 할 수 있지만, 엣지 경우는 2400 년까지는 발생하지 않으므로 무시해도 안전하다고 생각합니다. –

    +0

    @UncleBens : 넵 매크로는 지금까지 생각해 낸 유일한 해결책입니다 ... 참/거짓으로 평가되는 한 줄의 표현식이어야합니다. 솔직히 말해서 숙제는 모두 매우 어리 석다. –

    답변

    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)) 
    
    2

    표준 C++에서는 가능하지 않습니다. G ++에는 확장을 할 수있는 statement expressions이 있습니다.

    2

    나는 할 수 있다고 생각하지만 가능한 경우에도 정의 된 괄호 안에 범위 만 있고 그 범위 밖에서는 사용할 수 없습니다.

    4

    숙제의 목적은 변수를 사용하지 않고이 작업을 수행하도록 요청하는 것입니다. 시도하려는 작업은 그 목적을 무력화시킬 수 있습니다.

    +1

    5 월 - 적절한 라이브러리를 사용하겠습니까? – UncleBens

    +0

    그것이 의도라면, 과제는 그것을 요구해야합니다. – Chuck

    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 주위에 괄호가 실제로 필요하지만, 난하지 않습니다 가독성을 위해 포함됩니다. 코멘트를 보면


    UPDATE

    , 당신은 또한 그레고리력에 존재하지 않는 날짜를 확인하기 위해 유사한 규칙이 필요합니다.

    UPDATE 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++을 사용할 것이라는 것을 진지하게 생각합니다. 게다가, 나는 프로그래머가 버그를 수정하도록 배정받지 않을 것이다.

    +0

    29/2/1900 => 실패, 존재하지 않는 날짜 : - P –

    +0

    이 실패가 지속적인 영향을 미쳤던 한 지역, 현재까지는 http://www.joelonsoftware.com/items/2006/06/16.html을 참조하십시오. . (Go Lotus!) –

    1

    첫 번째 :하지 마십시오. 그것은 귀엽다, 그러나 그것을 허용하는 연장이 있더라도, 코드 골프는 거의 항상 그것이 해결하는 것보다 큰 슬픔을 일으키는 위험한 게임이다.

    좋아요, 다시 숙제에 정의 된대로 '진짜'질문으로 돌아갑니다. 추가 기능을 만들 수 있습니까? 그렇다면 변수에서 윤년인지 여부를 캡처하는 대신 올바른 값을 반환하는 isLeapYear (int year) 함수를 만듭니다.

    네, 두 번 이상 계산할 것입니다. 성능 문제가 끝나면 놀랄 정도로 놀랄 것입니다. 그리고 처음부터 걱정할 조기 최적화입니다.

    이 작업의 일환으로 함수를 작성할 수없는 경우 매우 놀랍습니다. 그것은 이런 운동의 절반 정도가 될 것 같습니다.

    ......

    좋아, 그래서 여기에 당신이해야 무엇에 대한 간단한 개요입니다.

    첫 번째 기본 - 월, 일, 년은 모두 0 - 11 월 (0을 가정), 0-30 일, 1 년을 제외한 모든 값을 가질 수 있습니다 (제약 조건이라고 가정).

    일단 지나면 1752 개의 특별한 경우를 확인해야 할 것입니다.

    '관련없는'월은 상당히 단순하게 처리 될 수 있습니다.

    윤년 사건은 두 가지 표현으로 나눌 수 있습니다. 윤년인지 여부 (그레고리 안/율리우스에 따라 추가로 세분 됨)와 해당 날짜가 유효한지 여부 포인트.

    areWithinRange (D, M, Y) & & passes1752SpecialCases (D, M, Y) & & passes30DayMonths (D, M, Y) :

    그래서, 최고 수준의, 당신의 표현은 다음과 같이 보입니다 & & passes31DayMonths (D, M, Y) & & passesFebruaryChecks (D, M, Y)

    우리는 우리가 적극적으로 규칙 휴식 (삼십일일에서 감지하면 우리는 우리의 하위 표현에서 false를 반환한다고 가정하면 일본 30DayMonth 규칙에 대한 une는 false를 반환하지만 2 월의 30 일은 무의미하고 사실로 전달됩니다.) 그러면 해당 수준의 논리가 정확하다고 할 수 있습니다.

    이 시점에서 필자는 개별 부분에 대해 별도의 함수를 작성합니다 (순수 식, 단일 return ... 문). 일단 그 위치를 얻으면 최상위 표현식의 메소드 호출을 확장 된 버전으로 바꿀 수 있습니다. 모든 것을 충분히 괄호로 묶어 놓으십시오.

    또한이 표현식을 사용하는 테스트 하네스 프로그램을 만들고 유효하고 잘못된 입력이 여러 개 있는지 확인하고 올바른 작업을하는지 확인합니다. 당신은 컷의 편의를 위해 함수에 그 쓰기와 같은 수행하여 최종 턴에 대한 붙여 넣을 수 있습니다 : 표현은 그 자체로 한 줄에있을 것입니다 때문에, 절단하기 쉬운 수 있습니다

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

    및 풀.

    로직을 단순화하는 다른 방법을 찾을 수 있습니다. 예를 들어, 1752 특수한 경우를 제외하고는 1에서 28 사이의 날짜는 항상입니다. 내가 당신을 위해 충분히 제공하지 않습니다

    +0

    사실 어떤 기능도 쓸 수 없습니다. 명시 적으로 나는 단 한 줄의 표현 인 –

    +0

    을 제출할 수 있다고 말합니다. 놀랍지 만 함수 액세스에서 상태를 숨김으로써 '부정 행위'하는 것을 막을 수 있다고 생각합니다. 그러나 매크로 솔루션은 기능과 동등한 것으로 간주 될 수 있습니다. 나는? : 연산자를 많이 사용해야하고 중복 된 코드가있을 수 있다고 생각합니다. 편리함을 제외하고 이와 같은 '순 함수 (pure function)'에 상태를 추가 할 이유가 없으므로 식과 같은 것을하는 것을 배우는 것은 좋은 연습입니다. 이 사건의 예상되는 투입물과 산출물은 무엇입니까? – kyoryu

    +0

    @kyoryu : 매크로를 사용하여 코드를 읽을 수있게 만들었습니다.? : 연산자로 예상되는 입력은 세 가지 "변수"dmy이고 출력은 true/false 여야합니다. –

    1

    귀하의 솔루션, 아마도 이러한 라인을 따라 갈 것입니다 :

    isJulian ? isJulianLeapyear : isGregorianLeapyear 
    

    , 그것은 더 구체적으로 만들려면이 같은 수 :

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

    당신에게 알고리즘이 정확한지 확인해야합니다. 나는 캘린더 전문가가 아니므로 그 사실을 알지 못합니다.

    0

    숙제 인 점을 감안할 때, 최선의 조언은 자신 만의 해결책을 도출하는 방법이라고 생각합니다.

    이 과제를 해결하려면 먼저 규칙을 어기면됩니다.

    1. I는 변수 d에 주어진 m, 및 Y는 C++을 작성 기능은 날짜의 유효성에 부울 결과를 반환한다. 필요에 따라 많은 비 재귀 적 도우미 함수를 사용하고 if, else if 및 else를 자유롭게 사용할 수 있지만 큰 소리로 반복하지는 않습니다.

    2. 나는 것 다음 인라인 모든 도우미 기능

    3. 내가 줄일 수있는 모든, 만약 다른 경우, 및 else 문에? : 표기

    I 변수의 내 사용을 제한에서 성공하면, 내가 어떤 변수를 하나의 함수에 모든 것을 줄일 수 있습니다 - 내가 추구하는 하나의 표현을 포함하는의 몸.

    행운을 비네. 기존 하나를 재사용 할 경우

    5

    <evil> 왜, 새로 정의 할 것인가? errno은 완벽한 임시 변수입니다. </evil>

    관련 문제