Giải quyết ký hiệu toán


14

Hãy tưởng tượng tôi có vô số bài toán về nhà (!) Mỗi ​​bài cho một số nguyên.

Ký hiệu vấn đề toán học là một ký hiệu để mô tả các tập hợp con của vấn đề bằng cách sử dụng các chỉ định vấn đề.

Biểu thức MPN có thể bao gồm một số điều:

  • Một giá trị duy nhất. Điều này đại diện cho một bộ chứa số : 99 -> {99}.
  • Một phạm vi đơn giản. Điều này thể hiện tập hợp chứa tất cả các số từ đầu đến cuối phạm vi : 10~13 -> {10, 11, 12, 13}. Nếu bên trái hoặc bên phải bị thiếu, thì chúng được giả sử là -Infinity hoặc Infinity tương ứng : ~10 -> {x|x ≤ 10}; ~ -> ℤ.
  • Một biểu thức MPN, theo sau là "bỏ qua" và một biểu thức MPN khác. Điều này thể hiện sự khác biệt của hai bộ : 10~20 skip 12~14 -> {10, 11, 15, 16, 17, 18, 19, 20}.
  • Hai biểu thức MPN, cách nhau bằng dấu phẩy. Điều này đại diện cho sự kết hợp của hai bộ : 1,8~9,15~17 -> {1,8,9,15,16,17}.

Toán tử "bỏ qua" liên kết chặt chẽ hơn toán tử dấu phẩy, vì vậy 16,110~112 skip 16 -> {16,110,111,112}(16 không được bao gồm trong tập hợp {110,111,112}, vì vậy việc loại trừ 16 không thành vấn đề.)

Bạn cũng có thể đặt biểu thức trong ngoặc đơn để định hướng: 1~9 skip (2~8 skip (3~7 skip (4~6 skip 5))) -> {1,3,5,7,9}

Đây là ngữ pháp:

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

Nhiệm vụ của bạn là viết một chương trình có hai đầu vào:

  • Biểu thức MPN
  • Một số

và đưa ra một số giá trị trung thực hoặc falsey tùy thuộc vào vấn đề đó có nằm trong tập được mô tả bởi biểu thức MPN hay không.

Thông số kỹ thuật

  • Bạn có thể giả sử rằng đầu vào đầu tiên là một biểu thức MPN được định dạng tốt (nghĩa là nó phù hợp với ngữ pháp trên)
  • Các số trong biểu thức MPN luôn là số nguyên. Chúng có thể âm hoặc bằng 0, nhưng sẽ không bao giờ có phần phân số.
  • Đây là , vì vậy bài nộp hợp lệ ngắn nhất (tính bằng byte) sẽ thắng.
  • Bạn có thể sử dụng các ký tự khác nhau cho ~,, nếu bạn muốn.

Các trường hợp thử nghiệm

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

Có thể sử dụng các ký tự khác để biểu diễn các toán tử không? Ví dụ sử dụng # thay vì ~
rahnema1

1
@ rahnema1 Cho ~,, nhưng không cho skip.
Esolanging Fruit

3
Tại sao ~ 10,5 ~ sai cho 4? Bởi vì đó là sự kết hợp giữa vô hạn đến 10 và 5 đến vô cùng, nên lần đầu tiên bao gồm 4
ev3commander

@ ev3commander Đã chỉnh sửa. Tôi luôn luôn làm hỏng các trường hợp thử nghiệm của tôi. Tôi cá rằng những thách thức của tôi sẽ rõ ràng hơn nếu tôi không thêm chúng: P
Esolanging Fruit

1
@ Challenger5 Tôi đã thêm một trường hợp thử nghiệm 6 skip 6,~mà tôi tin rằng tôi đã giải thích chính xác. Hai câu trả lời khác cho đến nay không thỏa mãn nó (một lần nữa, giả sử tôi đang giải thích chính xác). Nếu tôi hiểu nhầm xin vui lòng sửa nó và làm rõ, nhưng theo hiểu biết của tôi, nó sẽ phù hợp với bất cứ điều gì (đó là sự kết hợp của một tập hợp không có gì phù hợp với một tập hợp phù hợp với tất cả mọi thứ). Đây là những trường hợp tôi đã nói trước đó mà tôi nghĩ có thể giúp ích rất nhiều khi thử nghiệm các giải pháp của chúng tôi.
chiến binh

Câu trả lời:


3

PowerShell , 189 195 byte

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

Giải trình

Tôi đã sớm nhận ra rằng sự phổ biến làm cho điều này không thể thực hiện được để tạo ra các mảng và kiểm tra các giá trị.

Tôi đã xem xét các phạm vi nhưng trong .Net họ không có phạm vi cần thiết ( độ dài của phạm vi được giới hạn ở một số nguyên đã ký (32 bit), vì vậy ngay cả khi bạn có thể giới hạn phạm vi trong int 32 bit đã ký , Tôi sẽ không thể xử lý tất cả các phạm vi.

Vì vậy, tôi bắt đầu chỉ nghĩ về điều này về mặt bắt đầu và kết thúc, và cuối cùng là một loạt các bài kiểm tra boolean và bắt đầu tạo ra một loạt các biểu thức chính thay thế để biến MPN thành biểu thức boolean mà PowerShell hiểu được.

Về cơ bản, tôi đã chia nó thành một vài quy tắc:

  • Phạm vi dễ dàng hơn để làm việc với đầu tiên vì chúng không thể là biểu thức ở hai đầu, nhưng kết thúc mở là một nỗi đau để thực hiện trong thời gian ngắn. Tiền đề 2~8giống như nói n >=2 && n <=8, nhưng khi một trong những kết thúc bị mất, hãy bỏ qua &&và bên còn thiếu. Khi cả hai bị mất, ban đầu tôi sẽ chỉ thay thế nó bằng $true. Những gì tôi đã làm cuối cùng không thực sự kiểm tra cho các mặt còn thiếu, nhưng tôi chắc chắn bọc từng số ().
  • và sau đó thực hiện thay thế thẳng thay thế dấu ngoặc rỗng ()bằng giá trị đầu vào. Vì vậy, trong trường hợp MPN như ~8với giá trị đầu vào 55, thay thế đầu tiên sẽ tạo ra (55-ge()-and55-le(8)), sau đó thay thế thứ hai xuất hiện để làm cho nó (55-ge55-and55-le(8)), về cơ bản vô hiệu hóa phần đó của phạm vi.
  • Tiếp theo tôi phải xử lý các số riêng lẻ trong MPN, nhưng phải cẩn thận để không gây rối với những số tôi đã chèn từ trước. Nó thực sự chỉ là những con số trong ,danh sách được phân tách bằng dấu phẩy và những con số riêng lẻ trước hoặc sau một skip, vì vậy tôi đã sử dụng những cái nhìn dài không may.
  • skipvề cơ bản là giống như -and -notvì vậy tôi thẳng thay thế của skipđể -and!(sử dụng !như là viết tắt cho -not).
  • Điều khó khăn tiếp theo là thứ tự ưu tiên thấp cho các dấu phẩy còn lại. Ban đầu tôi chỉ thay thế chúng bằng -ornhưng nó không giải thích cho các biểu thức tiếp theo nên 16,17 skip 16đã tạo mã như thế nào ($n-eq16)-or($n-eq17) -and! ($n-eq16). Nó cần dấu ngoặc đơn, nhưng điều đó dường như không thể thực hiện được với một sự thay thế thẳng. Vì tất cả những thứ khác đã được thay thế ngoại trừ dấu phẩy và chúng có mức ưu tiên thấp nhất, tôi chỉ tách toàn bộ chuỗi được tạo trên các dấu phẩy còn lại, sau đó bọc từng phần tử trong ngoặc đơn và nối lại với nó -or.

Cuối cùng, mã được tạo chỉ được đưa vào Invoke-Expression( iex) để được thực thi và sau đó chúng ta nhận được kết quả boolean ( bạn có thể thấy mã được tạo thay vì kết quả ở đây ).

Việc này diễn ra quá lâu và tôi chắc chắn có một số chỗ để vắt thêm vài byte nữa, nhưng tôi không thể nhìn vào nó nữa :-p


2

Perl, 99 130 byte

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}

Hãy thử nó trên Ideone.

Ung dung:

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
Thất bại cho ~ -2 cho đầu vào -2. Ngoài ra khi chèn -? trước cả ba \ d *
Kjetil S.

@KjetilS. Đã sửa lỗi cho số âm và số không.
Denis Ibaev

mã đẹp (phân tích ngữ pháp đầy đủ thường không cần thiết, regexes dễ dàng hơn)
Kjetil S.

1

JavaScript (ES6), 221 292 287 309 274 277 278 byte

(-5 byte nhờ Okx)

(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,'-'))

Ồ Điều này không dễ dàng vì tất cả các trường hợp cạnh, nhưng tôi nghĩ rằng tôi đã làm nó. Tôi chỉ hy vọng không có trường hợp đặc biệt nào có thể phá vỡ các biểu thức thông thường được sử dụng. Tôi sẽ chơi golf này nhiều hơn bất cứ khi nào tôi có thể.

Kiểm tra đoạn trích

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 Nó nên hoạt động ngay bây giờ.
R. Kap

@ R.Kap Bạn có thể sử dụng 1/0cho Infinity.
Okx

@ R.Kap Tôi đã thử giá trị 6với biểu thức 6 skip 6,~mà tôi tin là nên truenhưng nó trả về false.
briantist

@briantist Trên thực tế, tôi tin rằng nên trả lại falsekhi skipáp dụng cho mọi thứ theo sau nó ( 6,~trong trường hợp này) miễn là nó không được gói trong ngoặc đơn. Vì vậy, tôi tin rằng nó sẽ trở truevề (6 skip 6),~chứ không phải là 6 skip 6,~với số nguyên đầu vào 6.
R. Kap

@briantist Nói cách khác, 6 skip 6,~không nên kết hợp vì nó đại diện cho sự khác biệt giữa tập hợp {6}và tập hợp {6,-Infinity...Infinity}.
R. Kap

0

Röda + bc, 183 byte

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"}

Điều này tương tự như câu trả lời của PowerShell (hoặc tôi nghĩ vậy, tôi không hiểu PowerShell). Nó lấy số làm đối số và mã làm giá trị trong luồng đầu vào, như thế này : main { push("1~9") | f(5) }.

Tôi nghĩ rằng nó hoạt động, ít nhất là nó giải quyết tất cả các trường hợp thử nghiệm. Kịch bản dưới đây có thể được sử dụng để xác minh điều này.

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
}

Và các bài kiểm tra:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.