Golf cho tôi một OOP!


26

Golf cho tôi một OOP!

Hai thành phần quan trọng của lập trình hướng đối tượng là kế thừa và thành phần. Cùng nhau, chúng cho phép tạo ra hệ thống phân cấp lớp đơn giản nhưng mạnh mẽ để giải quyết vấn đề. Nhiệm vụ của bạn là phân tích một loạt các câu lệnh về một hệ thống phân cấp lớp và trả lời các câu hỏi về hệ thống phân cấp.

Đầu vào

Một loạt các câu lệnh và câu hỏi về hệ thống phân cấp lớp, đọc từ tệp hoặc đầu vào tiêu chuẩn, tùy theo điều kiện nào là tốt nhất cho ngôn ngữ của bạn. Nếu bạn sử dụng tùy chọn tệp, tên tệp sẽ được chuyển làm đối số đầu tiên cho mã của bạn (đối số hàm hoặc đối số dòng lệnh, tùy theo bạn chọn). Định dạng như sau:

<statement> : <name> is a <name>. | <name> has a <name>.
<question> : Is <name> a <name>? | Does <name> have a <name>?
<name> : a-z | A-Z | sequence of alphanumerics or underscores, starting with a letter

Đầu vào sẽ luôn là câu lệnh, sau đó là câu hỏi. Tất cả các tên lớp sẽ bắt đầu bằng một chữ cái tiếng Anh viết hoa ( A-Z) và tất cả các tên thành viên sẽ bắt đầu bằng một chữ cái tiếng Anh viết thường ( a-z). Tất cả các tên đều phân biệt chữ hoa chữ thường - ABC123không cùng loại với Abc123.

Sẽ không có bất kỳ sự thừa kế theo chu kỳ nào - nếu Bđược thừa kế từ A, Asẽ không được thừa kế từ Bhoặc bất kỳ Bđứa con nào.

Chỉ tên lớp sẽ là một phần của hệ thống phân cấp - các câu lệnh như foo is a bar.hoặc document has a name.sẽ không xảy ra.

Đầu ra

Một loạt các giá trị trung thực hoặc falsey, dưới dạng câu trả lời cho các truy vấn, được ghi vào đầu ra tiêu chuẩn hoặc là giá trị trả về của hàm của bạn. Nếu bạn không có đủ thông tin để trả lời một câu hỏi (ví dụ: các câu hỏi liên quan đến tên mà bạn chưa thấy trong các tuyên bố), hãy trả lời với giá trị falsey.

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

Trường hợp 1:

Đầu vào:

B is a A.
C is a B.
A has a foo.
Does B have a foo?
Is C a A?
Is D a A?

Đầu ra:

True
True
False

Trường hợp 2:

Đầu vào:

Cop is a Person.
Criminal is a Person.
Sheriff is a Cop.
Crooked_Cop is a Cop.
Crooked_Cop is a Criminal.
BankRobber is a Criminal.
Cop has a badge.
Criminal has a criminal_record.
Person has a name.
Is Crooked_Cop a Person?
Does Criminal have a name?
Is Crooked_Cop a BankRobber?
Does Person have a potato?
Is Cop a Cop?

Đầu ra:

True
True
False
False
True

Quy tắc

  • Bạn có thể trả lời với một chức năng hoặc một chương trình
  • Sơ hở tiêu chuẩn bị cấm
  • Đây là , vì vậy câu trả lời đúng ngắn nhất bằng byte thắng
  • Câu trả lời chiến thắng sẽ được chọn trong một tuần

Chúc may mắn, và có thể OOP sẽ ở bên bạn!

Bảng xếp hạng

Đoạn trích Stack ở cuối bài này tạo bảng xếp hạng từ các câu trả lời a) dưới dạng danh sách các giải pháp ngắn nhất cho mỗi ngôn ngữ và b) dưới dạng bảng xếp hạng tổng thể.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

## Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Nếu bạn muốn bao gồm nhiều số trong tiêu đề của mình (ví dụ: vì điểm của bạn là tổng của hai tệp hoặc bạn muốn liệt kê riêng các hình phạt cờ của thông dịch viên), hãy đảm bảo rằng điểm thực tế là số cuối cùng trong tiêu đề:

## Perl, 43 + 2 (-p flag) = 45 bytes

Bạn cũng có thể đặt tên ngôn ngữ thành liên kết sau đó sẽ hiển thị trong đoạn trích:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


Làm thế nào là Does Criminal have a name?bằng True? Có phải tất cả các đối tượng có một tên?
J Atkin

4
@Jtkin Criminal is a Person. Person has a name.
Reto Koradi

À ... tôi đã bỏ lỡ điều đó.
J Atkin

Tôi có cần phải lấy tất cả đầu vào cùng một lúc không, hoặc tôi có thể đưa nó theo từng dòng như bảng điều khiển tương tác không? Nếu # 2, tôi có thể xuất ra một sự thật \ falsey ngay cả khi đầu vào là một thống kê không?
J Atkin

@JAtkin Tất cả cùng một lúc hoặc từng dòng, sự lựa chọn của bạn. Nếu đó là một tuyên bố, không nên có bất kỳ đầu ra. Chỉ có câu hỏi nhận được câu trả lời.
Mego

Câu trả lời:


13

CJam, 59 byte

q_'.e=\N/{)'?=\S/>_,(%}%/(__,*{(2$z~@f=.*\m*|}/ff{1$e=>:=N}

Điều này kết thúc ngay lập tức cho cả hai trường hợp thử nghiệm.

Nó hoặc in tên tên thứ hai của câu hỏi hoặc 1(cả hai sự thật), hoặc 0(giả).

Hãy thử trực tuyến trong trình thông dịch CJam .

Ý kiến

Do sự khác biệt giữa các lớp và các thành viên, thử thách tập trung vào việc tạo ra một thứ tự mà đầu vào cung cấp một định nghĩa một phần.

Chúng tôi xác định rằng xy iff x là một y hoặc x có một y .

Đối với trường hợp thử nghiệm đầu tiên, các tiểu bang đầu vào BMột , CBAfoo . Bởi vì bắc cầu, chúng tôi cũng có Bfoo , CMộtMộtfoo . Ngoài ra, vì tính phản xạ, xx luôn luôn đúng.

Do đó, đối với một đầu vào nhất định, do đó chúng tôi có thể trích xuất định nghĩa một phần của ≺ từ các câu lệnh, áp dụng độ xuyên sáng đủ số lần để hoàn thành định nghĩa và cuối cùng trả lời các câu hỏi.

q_     e# Push all input from STDIN and a copy.
'.e=   e# Count the number of dots/statements (C).
\N/    e# Split the original input at linefeeds.
{      e# For each line:
  )'?= e#   Pop the last character and check if it is a question mark.
       e#   Pushes 1 for '?', 0 for '.'.
  \S/  e#   Split the modified line at spaces.
  >    e#   Remove the first chunk ("Does" or "Is") for questions.
  _,(% e#   Keep the first and last element of the resulting array.
}%/    e# Split the line array into chunks of length C.
(_     e# Extract the first chunk (statements) and push a copy.
       e# The original becomes an accumulator for ≺.
_,*    e# Repeat the statements C times.
{      e# For each of the repeated statements:
  (    e#   Shift out the first name.
       e#     ["w" "x"] -> ["x"] "w"
  2$z~ e#   Copy the accumulator, zip it and dump.
       e#     [["x" "y"] ["z" "w"]] -> ["x" "z"] ["y" "w"]
  @f=  e#   Rotate the shifted out name on top and check for equality.
       e#     ["y" "w"] "w" -> [0 1]
  .*   e#   Vectorized string repetition.
       e#     ["x" "z"] [0 1] -> ["" "z"]
  \m*  e#   Swap the result with the shifted array and apply Cartesian product.
       e#     ["" "z"] ["x"] -> [["" "x"] ["z" "x"]]
       e#   This accounts for transitivity; we had ["w" "x"] and ["z" "w"],
       e#   so now we have ["z" "x"].
  |    e#   Perform set union with the accumulator to add the new pairs.
}/     e#
ff{    e# For each of the questions on the bottom of the stack.
  1$e= e#   Count the occurrences of the question pair in the accumulator.
  >    e#   Remove 0 or 1 elements from the question pair.
  :=   e#   Check for equality.
       e#   If the question pair occurs in the accumulator, this pushes the
       e#   second name of the question pair. Otherwise, it pushes 1 if the
       e#   names are equal (to account for reflexivity) and 0 otherwise.
  N    e#   Push a linefeed.
}      e#

2
Điều này rất ấn tượng khi xem xét rằng CJam không có các lớp: D
Beta Decay

Thật là đẹp
Mego

Các lớp @BetaDecay về cơ bản là các tập hợp lồng nhau; các lớp học được thực hiện trong mọi ngôn ngữ. Nói trong ví dụ đầu tiên. C:{B:{A:{foo:{}}}}
A̲̲

8

Python 3, 431 331 308 byte

o={}
f={}
def h(z,f):
 if z not in o:f[z]=[z];o[z]=[]
while 1:
 g=input().split(' ');r=2;l=g[-1][:-1]
 if'.'in g[3]:
  if'i'in g[1]:h(g[0],f);h(l,f);f[g[0]]+=f[l]
  if'h'in g[1]:o[g[0]]+=l,
 else:
  if'I'in g[0]:r=any(l in z for z in f[g[1]])
  if'D'in g[0]:r=any(l in o[z] for z in f[g[1]])
 if r<2:print(r)

Đây là phiên bản đầy đủ với ý kiến

objects = {}
synonyms = {}

def createObject(name):
    """
    Create a object with `name` if is does not yet exist and start a synonym tree.
    """
    if name not in objects:
        synonyms[name] = [name]
        objects[name] = []

# use this to read from a file
# with open("questions.txt") as file: 
#     for l in file:
        # print(">>> " + l, end='')
        # inArg = l.replace("\n","").split(" ")


while True: # to read from a file comment this
        inArg = input(">>> ").split(" ") # and this out

        out = -1

        if '.' in inArg[3]: # statement
            last = inArg[3].replace('.','')

            if 'i' in inArg[1]: # is a
                createObject(inArg[0])
                createObject(last)
                synonyms[inArg[0]] += synonyms[last]

            if 'h' in inArg[1]: # has a
                objects[inArg[0]] += [last]

        else:# question
            last = inArg[-1].replace('?','')

            createObject(inArg[1])
            if 'I'in inArg[0]: # Is a
                out = any([last in syn for syn in synonyms[inArg[1]]])

            if 'D'in inArg[0]: # Does have a
                out = any(last in objects[syn] for syn in synonyms[inArg[1]])

        if out != -1:
            print(out)

Đầu ra cho trường hợp thử nghiệm # 1:

True
True
False

Trường hợp 2

True
True
False
False
True

Tôi đã xóa các lệnh gỡ lỗi cho rõ ràng trong chương trình chính, nhưng nếu bạn muốn thấy chúng chỉ cần nhìn vào lịch sử


Thay vì sử dụng global ftrong h(z), sử dụng def h(z,f)và vượt qua toàn cầu ftrong khi gọi nó. Trên thực tế, bạn hoàn toàn không cần h(z)- chỉ cần đặt cơ thể nơi bạn gọi nó. Bạn không cần r=2, và bạn chỉ có thể làm print(r)mà không cần if, vì bạn cần xuất giá trị falsey cho các truy vấn sai. Bạn có thể đổi tên synthành zvà cạo một vài byte ở đó. Tôi không nghĩ rằng bạn cần sự hiểu biết []xung quanh danh sách của bạn trong lần đầu tiên any.
Mego

Bạn cũng sử dụng emột lần, vì vậy bạn có thể loại bỏ định nghĩa và chỉ sử dụng [a,b,c,d]. Thay vì if s(i,g) is not None, do if s(i,g)- re.Matchcác đối tượng luôn được ước tính Truenếu tìm thấy kết quả khớp. Bạn cũng có thể thả 2 byte với f[x]+=f[y].
Mego

@Mego Wow, cảm ơn vì tất cả những lời khuyên. Tôi sẽ cần đưa chúng vào sau.
J Atkin

Bài đăng này có thể sẽ giúp bạn rất nhiều
Mego

@Mego Cảm ơn rất nhiều, giảm xuống còn 396. Tôi sẽ đăng là trong thời gian ngắn.
J Atkin

4

Haskell, 157 byte

o s=v(x 0#k)#(x 1#q)where(k,q)=break((=='?').l.l)(words#lines s)
x n w=(w!!n,init$l w)
v k(a,c)=a==c||or[v k(b,c)|b<-snd#(filter((==a).fst)k)]
(#)=map
l=last

Đưa chuỗi cho o. Không chắc chắn nếu các phần tử tạo xv('giải nén' và 'xác minh') cắt giảm nhiều hơn so với việc tạo mapmột phần tử, hoặc nếu cả hai đều có thể.

EDIT: Giải thích

Vì vậy, (#)là cách bạn xác định một toán tử infix, tôi sử dụng nó như một cách viết tắt map, áp dụng một hàm cho từng thành phần của danh sách. Giải quyết bí danh này và các bí danh khác l, tránh toán tử 'ứng dụng chức năng trực tiếp' $và thêm nhiều dấu ngoặc đơn và khoảng cách mọi thứ, và với tên hàm thực chúng ta đến:

oop string = map (verify (map (extract 0) knowledge)) (map (extract 1) questions)
 where (knowledge,questions) = break ((=='?').last.last) (map words (lines string))

extract n wordlist = (wordlist!!n,init (last wordlist))

verify knowledge (a,c) = (a==c)
               || or [verify knowledge (b,c) | b <- map snd (filter ((==a).fst) knowledge)]

map words (lines string) là danh sách các danh sách từ của từng dòng trong chuỗi đầu vào.

(=='?').last.last là một vị ngữ cho biết liệu chữ cái cuối cùng trong từ cuối cùng của dòng có phải là dấu hỏi hay không, tức là dòng đó có phải là câu hỏi hay không.

break phá vỡ danh sách trong một bộ của phần đầu tiên mà không có câu hỏi (tất cả các câu) và phần từ câu hỏi đầu tiên trên (tất cả các câu hỏi).

mapping extract ntrên những từ này lấy ra từ mỗi danh sách các yếu tố chúng ta thực sự muốn, từ nthứ nhất (trong câu lệnh là từ đầu tiên - vì vậy n == 0, và trong câu hỏi là từ thứ hai - vì vậy n == 1) sử dụng !!toán tử và từ cuối cùng, từ đó chúng ta phải cắt chữ cái cuối cùng ( '.'hoặc '?') bằng cách sử dụng init.

(Lưu ý rằng tôi hoàn toàn bỏ qua viết hoa, đó là vì tôi hoàn toàn bỏ qua sự phân biệt giữa các lớp và các thành viên, các thành viên chỉ là những chiếc lá được xây dựng bởi cơ sở tri thức (nhưng không phải tất cả các lá đại diện cho các thành viên, chúng cũng có thể là các lớp không có lớp con cũng không phải thành viên ), trong đó mỗi nút con đại diện cho một lớp con hoặc thành viên của nút cha mẹ của nó đại diện cho điều gì. TÔI CHỈ THỰC HIỆN ĐÂY LÀ MỘT ĐIỀU SAU ĐỂ LÀM trong trường hợp không được OP đề cập. Sẽ sớm chỉnh sửa giải pháp.)

Bây giờ, map (extract 0) knowledgemap (extract 1) questionslà danh sách các bộ tên đại diện cho mối quan hệ lớp con hoặc thành viên của mối quan hệ thứ nhất với thứ hai.

Các bộ dữ liệu trong map (extract 0) knowledgetất cả các mối quan hệ thực sự, những bộ trong map (extract 1) questionshiện được ánh xạ verifyhàm, với đối số đầu tiên được đặt thành map (extract 0) knowledge.

(Từ bây giờ, bên trong verify, knowledgelà một tên tham số và đề cập đến extractdanh sách tuple đã ed.)

(Ngoài ra, khi đọc verify, hãy lưu ý rằng trong khi ||(sau khi ngắt dòng không liên tục để tránh cuộn ngang trên SE) là một sự phân biệt boolean bình thường giữa trường hợp 'phản xạ' và 'đệ quy', hãy orgập nó qua danh sách, nghĩa là kiểm tra nếu có danh sách thành phần là đúng.)

Bây giờ, một mối quan hệ rõ ràng là chính xác nếu nó là phản xạ. Nói đúng ra, không, một potatokhông một potato(và nó không phải là ngay cả một theo nghĩa 'là' được sử dụng ở đây, như trong 'A Cop là một Cop'), nhưng đó mới chỉ là điều kiện chấm dứt mà bao gồm tất cả các mối quan hệ sau đi xuống cây (không giống như trong trường hợp cây thật có nghĩa là 'hướng về phía những chiếc lá').

Trong tất cả các trường hợp khác, chúng tôi cố gắng lấy một tuple từ knowledge(sau khi chúng tôi chỉnh filtersửa để đảm bảo rằng chúng tôi chỉ nhìn thấy các cặp có cùng yếu tố đầu tiên mà chúng tôi muốn kiểm tra) và tiếp tục từ nơi nó chỉ đến. Việc hiểu danh sách liên quan đến tất cả các bộ dữ liệu có thể để tiếp tục và gọi verifylại trong mỗi trường hợp. Một ngõ cụt sẽ chỉ có một danh sách trống ở đây và trả về falsetổng thể, và do đó không ảnh hưởng đến thể hiện của verifynó được gọi bởi.


Bạn có thể thêm một lời giải thích ngắn cho những người không thông thạo haskell?
J Atkin

Hạnh phúc! Tôi chỉ không làm điều đó cho mỗi bài viết cho đến khi được yêu cầu.
Leif Willerts

Được rồi cảm ơn! (phụ)
J Atkin

Wow, đó là một số lời giải thích.
J Atkin

2
Tôi vừa đọc xong nửa đầu Learn you a haskell for great good!và bây giờ tôi đã hiểu điều này! (Câu trả lời này thực sự là điều khiến tôi tìm hiểu thêm về haskell và FP, và nó thật tuyệt!)
J Atkin

4

JavaScript, 265 263 byte

for(o={};i=prompt().split(/\W/);)a=i[0],b=i[1],d=i[2],b=="is"?((o[a]=o[a]||{p:[],k:{}}).p.push(d),o[d]=o[d]||{p:[],k:{}}):b=="has"?o[a].k[d]=1:alert(o[b]&&(a>"E"?b==d|(c=n=>~(p=o[n].p).indexOf(d)|p.some(c))(b):(c=n=>o[n].k.hasOwnProperty(i[4])|o[n].p.some(c))(b)))

Nhập một chuỗi trống để thoát.

Giải trình

for(
  o={};                               // o = all objects
  i=prompt().split(/\W/);             // i = command as an array of words
)
  a=i[0],                             // a = first word
  b=i[1],                             // b = second word
  //c=i[2],                           // c = third word
  d=i[3],                             // b = fourth word
  //e=i[4],                           // e = fifth word

  // Case: <name> is a <name>.
  b=="is"?(
    (o[a]=o[a]||{p:[],k:{}})          // create the object if it does not exist
      .p.push(d),                     // add the parent to the object's list of parents
    o[d]=o[d]||{p:[],k:{}}            // create the parent if it does not exist
  ):

  // Case: <name> has a <name>.
  b=="has"?
    o[a].k[d]=1                       // set the specified property

  :
  alert(                              // display the responses to the questions
    o[b]                              // false if the queried object does not exist
    &&(

      // Case: Is <name> a <name>?
      a>"E"?                          // "Is" > "E" and "Does" < "E"
        b==d                          // check if it is itself
        |(c=n=>
          ~(p=o[n].p)                 // p = direct parents of current object
            .indexOf(d)               // check direct parents for the object
          |p.some(c)                  // check the grandparents
        )(b)

      // Case: Does <name> have a <name>?
      :
        (c=n=>
          o[n].k.hasOwnProperty(i[4]) // check if this object has the property
          |o[n].p.some(c)             // check it's parents for the property also
        )(b)
    )
  )

Bạn có thể sử dụng string.split(" ");?
J Atkin

@JAtkin Tôi đã sử dụng .match(/\w+/g)để xóa dấu câu từ các từ.
dùng81655

Tôi đã thấy điều đó, nhưng sẽ không .split(" ")ngắn hơn hay tôi đang thiếu thứ gì? (Tôi không biết javascript)
J Atkin

@JAtkin Nếu tôi đã sử dụng .splittôi cũng sẽ phải sử dụng .slice(0,-1)(hai lần) vì B is a A.sẽ tạo Bkế thừa A.(với .).
dùng81655

@JAtkin Thật ra tôi mới phát hiện ra rằng split chấp nhận các biểu thức chính quy để tôi có thể sử dụng .split(/\W/). Cảm ơn vì đã khiến tôi phải nhìn lên!
dùng81655
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.