수학 문제 표기법 풀기


14

각 정수에 주어진 숙제 문제 (!)가 무한하다고 상상해보십시오.

수학 문제 표기법은 문제 지정자를 사용하여 문제의 하위 집합을 설명하는 표기법입니다.

MPN 표현식은 여러 가지로 구성 될 수 있습니다.

  • 단일 값. 숫자가 포함 된 집합을 나타냅니다 99 -> {99}.
  • 간단한 범위. 범위의 처음부터 끝까지 모든 숫자가 포함 된 집합을 나타냅니다 10~13 -> {10, 11, 12, 13}. 왼쪽 또는 오른쪽이없는 경우 각각 -Infinity 또는 Infinity 인 것으로 가정합니다. ~10 -> {x|x ≤ 10}; ~ -> ℤ.
  • MPN 식, "skip"및 다른 MPN식이 뒤 따릅니다. 이것은 두 세트의 차이점을 나타냅니다 10~20 skip 12~14 -> {10, 11, 15, 16, 17, 18, 19, 20}.
  • 쉼표로 구분 된 두 개의 MPN 표현식. 이것은 두 세트의 합집합을 나타냅니다 1,8~9,15~17 -> {1,8,9,15,16,17}.

"건너 뛰기"연산자는 쉼표 연산자보다 꽉 묶이므로 16,110~112 skip 16 -> {16,110,111,112}16은 세트에 포함 {110,111,112}되지 않으므로 16을 제외하면 문제가되지 않습니다.

명확성을 위해 괄호 안에 표현식을 넣을 수도 있습니다. 1~9 skip (2~8 skip (3~7 skip (4~6 skip 5))) -> {1,3,5,7,9}

이것은 문법입니다 :

<expr>  ::= "(" <expr> ")"
         || <number>
         || [<number>] "~" [<number>]
         || <expr> "skip" <expr>
         || <expr> "," <expr>

당신의 임무는 두 가지 입력이 필요한 프로그램을 작성하는 것입니다.

  • MPN 표현
  • 숫자

MPN 표현식에 의해 설명 된 세트에 문제가 있는지 여부에 따라 일부 참 또는 거짓 값을 출력합니다.

명세서

  • 첫 번째 입력이 올바른 형식의 MPN 표현식이라고 가정 할 수 있습니다 (즉, 위의 문법과 일치 함).
  • MPN 표현식의 숫자는 항상 정수입니다. 음수이거나 0 일 수 있지만 소수 부분은 절대 없습니다.
  • 이것은 이므로 가장 짧은 유효한 제출 (바이트 단위로 측정)이 이깁니다.
  • 원하는 경우 ~및에 다른 문자를 사용할 수 있습니다 ,.

테스트 사례

10~20             14 -> True
10~20             20 -> True
10~20 skip 14~18  17 -> False
~ skip 6          8  -> True
16,17 skip 16     16 -> True
(16,17) skip 16   16 -> False
~10,5~            8  -> True
~10,5~            4  -> True
6 skip 6,~        6  -> True

?는 ~ 대신 #을 사용하여 사업자 .FOR의 예를 나타 내기 위해 다른 문자를 사용하는 것이 가능
rahnema1

1
@ rahnema1 ~,에는 해당되지 않습니다 skip.
Esolanging 과일

3
왜 ~ 10,5 ~가 4에 대해 거짓입니까? 그것이 10의 무한대와 5의 무한대의 결합이기 때문에 첫 번째는 4
ev3commander

@ ev3commander가 편집되었습니다. 나는 항상 테스트 케이스를 망쳤다. 내가 추가하지 않으면 내 도전은 더 명확해질 것입니다 : P
Esolanging Fruit

1
@ Challenger5 올바르게 해석 했다고 생각6 skip 6,~ 되는 테스트 사례 를 추가했습니다 . 다른 두 가지 답변은 지금까지 그것을 만족시키지 못합니다 (다시 말하면 올바르게 해석한다고 가정). 내가 잘못 이해했다면 그것을 수정하고 명확히하십시오. 그러나 내 이해에서, 그것은 무엇이든 일치해야합니다 (그것은 모든 것과 일치하는 세트와 아무것도 일치하지 않는 세트의 조합입니다). 이것들은 솔루션을 테스트 할 때 많은 도움이 될 수 있다고 생각한 사례입니다.
briantist

답변:


3

PowerShell , 189 195 바이트

param($m,$q)('$m',"'(\d*)~(\d*)','($q-ge(`$1)-and$q-le(`$2))'","'\(\)',$q","'((?<=,|skip )\d+|\d+(?=,| skip))','($q-eq`$1)'","'skip','-and!'"-join'-replace'|iex|% Sp* ','|%{"($_)"})-join'-or'|iex

설명

나는 무한 성이 배열을 생성하고 값을 테스트하기 위해 이것을 불가능하게 만든다는 것을 일찍 깨달았습니다.

범위를 살펴 보았지만 .Net에서는 필요한 범위가 없습니다 (범위의 길이 는 부호있는 (32 비트) 정수로 제한되므로 범위를 부호있는 32 비트 int로 제한해도 괜찮습니다. , 모든 범위를 처리 할 수 ​​없었습니다.

그래서 나는 시작과 끝의 관점에서 이것에 대해 생각하기 시작했고 궁극적으로 일련의 부울 테스트를 시작하고 MPN을 PowerShell이 ​​이해하는 부울 식으로 변환하기 위해 많은 정규식 대체를 만들기 시작했습니다.

나는 기본적으로 이것을 몇 가지 규칙으로 나누었습니다.

  • 범위는 양쪽 끝의 표현이 될 수 없기 때문에 작업하기가 더 쉬웠지만 개방형은 곧 구현하기가 어려웠습니다. 전제는 2~8마치 말하는 것과 n >=2 && n <=8같지만, 끝 중 하나가 빠지면 &&빠진 쪽을 빼십시오 . 둘 다 누락되면 원래는로 대체하려고했습니다 $true. 내가 한 일은 실제로 누락 된면을 전혀 테스트하지는 않았지만 각 숫자를에 래핑했습니다 ().
  • 빈 괄호 ()를 입력 값으로 바꾸는 직선 대체를 수행하십시오 . 따라서 ~8입력 값이 같은 MPN의 경우 55첫 번째 대체가 생성 된 (55-ge()-and55-le(8))다음 두 번째 대체가 생성 되어 (55-ge55-and55-le(8))본질적으로 범위의 해당 부분을 무효화합니다.
  • 다음으로 MPN의 개별 숫자를 처리해야했지만 이전에 삽입 한 숫자를 혼동하지 않도록주의해야했습니다. 실제로 쉼표로 구분 ,된 목록의 숫자와 a 전후의 개별 숫자 skip이므로 불행히도 긴 둘러보기를 사용했습니다.
  • skip기본적으로 동일하다 -and -not내가 직선의 대체 않도록 skip-and!(사용 !에 대한 속기로 -not).
  • 다음으로 까다로운 것은 나머지 쉼표의 우선 순위가 낮았습니다. 나는 원래 그것들을 단지 그것들로 대체 -or했지만 후속 표현식을 설명하지 않았으므로 16,17 skip 16와 같은 코드를 생성했다 ($n-eq16)-or($n-eq17) -and! ($n-eq16). 괄호가 필요했지만 곧바로 대체 할 수없는 것처럼 보였습니다. 쉼표를 제외한 다른 모든 항목이 교체되었으며 우선 순위가 가장 낮으므로 생성 된 전체 문자열을 나머지 쉼표로 분할 한 다음 각 요소를 괄호로 묶고 다시 결합했습니다 -or.

궁극적으로 생성 된 코드는 Invoke-Expression( iex)로 파이프되어 실행 된 다음 부울 결과 를 얻습니다 (결과 대신 생성 된 코드를 볼 수 있음 ).

이것은 너무 오래 걸렸으며 몇 바이트를 더 넣을 공간이 있다고 확신하지만 더 이상 볼 수는 없습니다.


2

펄, 99130 바이트

sub f{($_,$n)=@_;s/(-?\d+)?~(-?\d+)?|(-?\d+)/!(defined$3?$n!=$3:length$1&&$1>$n||length$2&&$n>$2)+0/ge;s/skip/&&!/g;s/,/||/g;eval}

Ideone에서 사용해보십시오.

언 골프 드 :

sub f {
    my ($e, $n) = @_;

    $e =~ s/(-?\d+)?~(-?\d+)?|(-?\d+)/ (defined($3) ? $n == $3 : (!length($1) || $n >= $1) && (!length($2) || $n <= $2)) + 0 /ge;
    $e =~ s/skip/ && ! /g;
    $e =~ s/,/ || /g;

    return eval($e);
}

1
입력 -2에 대해 ~ -2에 실패합니다. 삽입 할 때도-? 3 일 전까지
Kjetil S.

@KjetilS. 음수와 0으로 고정되었습니다.
Denis Ibaev

좋은 코드 (전체 날려 문법이 자주 필요하지 구문 분석, 정규 표현식에가 쉽다)
Kjetil S.

1

자바 스크립트 (ES6) 221 292 287 309 274 277 278 바이트

(OKX 덕분에 5 바이트)

(j,v,m=1/0,Z=/(skip)([^,]+)/g)=>eval(j[M='replace'](/(-?\d*)~(-?\d*)/g,(e,a,b)=>(a[M]('-','#')||-m)+'<='+(T=v[M]('-','#'))+'&&'+T+'<='+(b[M]('-','#')||m))[M](Z,i=o=>o.match(Z)?i(o[M](Z,'&&!($2)')):o)[M](/,/g,'||')[M](/(^|[^=&#\d])(\d+)([^<\d]|$)/g,'$1$2=='+v+'$3')[M](/#/g,'-'))

와. 모든 경우 때문에 쉽지는 않았지만 내가 한 것 같습니다. 나는 정규 표현식을 깨뜨릴 수있는 특별한 경우가 없기를 바랍니다 . 나는 가능할 때마다 이것을 더 골프 질 것이다.

테스트 스 니펫

D=(j,v,m=1/0,Z=/(skip)([^,]+)/g)=>eval(j[M='replace'](/(-?\d*)~(-?\d*)/g,(e,a,b)=>(a[M]('-','#')||-m)+'<='+(T=v[M]('-','#'))+'&&'+T+'<='+(b[M]('-','#')||m))[M](Z,i=o=>o.match(Z)?i(o[M](Z,'&&!($2)')):o)[M](/,/g,'||')[M](/(^|[^=&#\d])(\d+)([^<\d]|$)/g,'$1$2=='+v+'$3')[M](/#/g,'-'))
MPN Expression:<input type="text" value="1~9 skip (2~8 skip (3~7 skip (4~6 skip 5)))" id="MPN"></input>
<br>
Integer:<input type="number" id="INT" value=6></input>
<input type="button" value="Submit" onclick="T=r=>document.getElementById(r).value;console.log(D(T('MPN'),T('INT')))"></input>


@AriaAx 이제 작동합니다.
R. Kap

R.Kap @ 당신은 사용할 수 있습니다 1/0에 대한 Infinity.
Okx

@ R.Kap 나는 믿어야 할 6표현으로 가치 를 시험해 보았지만 그것을 돌려줍니다 . 6 skip 6,~truefalse
briantist

@briantist 사실, 난 그 생각 한다 반환 false으로 skip적용 모든 것을 (그 다음 6,~이 경우)가되는만큼 되지 괄호 안에 감쌌다. 따라서, 나는 그것이 반환해야합니다 생각 true(6 skip 6),~아닌 6 skip 6,~정수 입력을 6.
R. Kap

@briantist 즉, 6 skip 6,~일치 안 아무 는 세트 간의 차이로서 나타내고, {6}상기 세트 {6,-Infinity...Infinity}.
R. Kap

0

로다 + bc, 183 바이트

f x{{["x=",x,"\n"];replace" ","",",","||","skip\\(","&&!","skip([0-9~]+)","&&!($1)","(?<!~|\\d)(\\d+)(?!~|\\d)","x==$1","(\\d*)~(\\d*)","x>=($1)&&x<=($2)","\\(\\)",x;["\n"]}|exec"bc"}

이것은 PowerShell 답변과 비슷합니다 (또는 PowerShell을 이해하지 못한다고 생각합니다). 다음과 같이 숫자를 인수로, 코드를 입력 스트림의 값으로 사용합니다 main { push("1~9") | f(5) }.

나는 그것이 효과가 있다고 생각합니다. 적어도 모든 테스트 사례를 해결합니다. 아래 스크립트를 사용하여이를 확인할 수 있습니다.

main {
    readLines("/tmp/tests.txt") | split(sep=";") | for code, num, ans do
        push(code, " -> ")
        print(code) | replace" ","",",","||","skip\\(","&&!","skip([0-9~]+)","&&!($1)","(?<!~|\\d)(\\d+)(?!~|\\d)","x==$1","(\\d*)~(\\d*)","x>=($1)&&x<=($2)","\\(\\)",num
        a := push(code) | f(num) | head()
        result := push("OK") if [ (a = "0" and ans = "False") or (a = "1" and ans = "True") ] else push("FAIL")
        print code, " ; ", num, " -> ", a, " ", ans, " (", result, ")\n"
    done
}

그리고 테스트 :

10~20;14;True
10~20;20;True
10~20 skip 14~18;17;False
~ skip 6;8;True
16,17 skip 16;16;True
(16,17) skip 16;16;False
~10,5~;8;True
~10,5~;4;True
6 skip 6,~;6;True
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.