打我一个OOP!


26

打我一个OOP!

面向对象编程的两个重要组成部分是继承和组合。它们一起允许创建简单而强大的类层次结构来解决问题。您的任务是解析有关类层次结构的一系列语句,并回答有关层次结构的问题。

输入项

从文件或标准输入中读取关于类层次结构的一系列语句和问题,以最适合您的语言的情况为准。如果使用file选项,文件名将作为第一个参数传递给代码(函数参数或命令行参数,无论您选择哪个)。格式如下:

<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

输入将始终是语句,然后是问题。所有班级名称A-Z均以大写英文字母()开头,所有成员名称均以小写英文字母(a-z)开头。所有名称均区分大小写- ABC123与的类不同Abc123

不会有任何周期性继承-如果B继承自AA不会继承B或任何B的子代。

只有类名将成为层次结构的一部分-诸如foo is a bar.document has a name.不会发生这样的语句。

输出量

一系列真值或假值,作为对查询的答案,写入标准输出或作为函数的返回值。如果您没有足够的信息来回答问题(例如,涉及您在语句中未曾看到的姓名的问题),请使用假值进行回答。

测试用例

情况1:

输入:

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?

输出:

True
True
False

情况2:

输入:

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?

输出:

True
True
False
False
True

规则

  • 您可以使用功能或程序来回答
  • 禁止出现标准漏洞
  • 这是,因此最短的正确答案(以字节为单位)将获胜
  • 获奖答案将在一周内选定

祝您好运,OOP与您同在!

排行榜

这篇文章底部的堆栈摘录从答案a)生成排行榜,答案是每种语言的最短解决方案列表,b)则是总体排行榜。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

## Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以通过打败旧分数保持标题。例如:

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

如果要在标头中包含多个数字(例如,因为您的分数是两个文件的总和,或者您想单独列出解释器标志罚分),请确保实际分数是标头中的最后一个数字:

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

您还可以将语言名称设置为链接,然后该链接将显示在代码段中:

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


怎么Does Criminal have a name?等于True?所有对象都有名称吗?
J Atkin

4
@JAtkin Criminal is a PersonPerson has a name
Reto Koradi

啊...我错过了。
J Atkin

我是否需要一次接受所有输入,还是可以像交互式控制台一样逐行接收?如果为#2,即使输入是陈述,我也可以输出true \ falsey吗?
J Atkin

@JAtkin全部或一次一行地选择。如果是声明,则不应有任何输出。只有问题才能得到答案。
Mego 2015年

Answers:


13

CJam,59个字节

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

这两个测试案例都立即完成。

它要么打印问题的第二名,要么打印1(真),要么打印0(假)。

CJam解释器中在线尝试。

理念

由于类和成员之间存在区别,因此挑战归结为创建一个预定义,为此输入提供了部分定义。

我们定义XŸ当且仅当XÿXÿ

对于第一个试验的情况下,输入状态即ÇFOO。由于传递的,我们也有Ç一个一个FOO。同时,由于反身性,XX始终是真实的。

因此,对于给定的输入,我们可以从语句中提取partial的部分定义,应用传递性足够的时间以完成the的定义并最终回答问题。

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
考虑到CJam没有课程,这令人印象深刻:D
Beta Decay

这很漂亮。
Mego 2015年

@BetaDecay类本质上是嵌套集;类以每种语言实现。在第一个示例中说。C:{B:{A:{foo:{}}}}
A̲̲

8

Python 3中,431个 331 308字节

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)

这是带注释的完整版本

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)

测试用例#1的输出:

True
True
False

案例2:

True
True
False
False
True

为了清楚起见,我在主程序中删除了调试命令,但是如果您想查看它们,只需查看历史记录即可


而不是使用global fin h(z),而是在调用它时使用def h(z,f)并传递global fin。实际上,您根本不需要h(z)-只需将身体放在您​​称之为它的位置即可。您不需要r=2,而print(r)无需使用if,因为您需要为错误查询输出一个falsey值。您可以重命名syn为,z并在那里删除几个字节。我认为您不需要[]首先了解列表any
Mego 2015年

您还可以使用e一次,因此您可以取消定义,而只需使用即可[a,b,c,d]。相反的if s(i,g) is not None,做的if s(i,g)- re.Match对象总是评价True,如果发现匹配。您还可以使用删除2个字节f[x]+=f[y]
Mego

@Mego Wow,感谢所有提示。我需要稍后再放入。
J Atkin

这篇文章可能会帮助你出了很多
美高

@Mego非常感谢,现在降至396。我会在不久后发布。
J Atkin

4

Haskell,157个字节

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

将字符串给o。不知道制作xv('提取'和'验证')缀是否比制作map一个缀更有意义,或者两者都可行。

编辑:解释

因此,这(#)是定义infix运算符的方式,我将其用作的简写形式map,将函数应用于列表的每个元素。解决这个别名和另一个别名l,避免使用“直接函数应用程序”运算符,$并添加更多的括号并将空格隔开,并使用真实的函数名得出:

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) 是输入字符串中每行的单词列表的列表。

(=='?').last.last 是谓词,指示行的最后一个单词中的最后一个字母是否为问号,即该行是否为问题。

break 在没有问题的第一部分(所有语句)和来自第一个问题的部分(所有问题)的元组中拆分列表。

mapextract n在这些单词上执行ping操作,从每个单词列表中提取出我们真正想要的元素,n第一个(在语句中为第一个单词-so n == 0,在问题中为第二个单词-so n == 1),使用!!运算符和最后一个元素,必须使用剪切最后一个字母('.''?'init

(请注意,我完全忽略了大小写,这是因为我完全忽略了类和成员之间的区别,成员只是由知识库构建的树的叶子(但并非所有叶子都代表成员,它们也可能是既没有子类也没有成员的类),其中每个子节点代表其父节点代表的子类或成员。我只是意识到,在OP未涵盖的情况下,这是一件很糟糕的事情。请尽快编辑解决方案。)

现在,map (extract 0) knowledgemap (extract 1) questions是代表第一个到第二个的子类或成员关系的名称元组列表。

in map (extract 0) knowledge中的元组都是真实的关系,in map (extract 1) questions中的元组现在被映射到verify函数上,第一个参数设置为map (extract 0) knowledge

(从现在开始,inside verifyknowledge是一个参数名称,并引用已extract编辑的元组列表。)

(此外,在阅读时verify,请注意,尽管||(为了避免在SE上进行水平滚动而进行了出色的换行,这是“反身”和“递归”情况下的布尔布尔分离),但将其or折叠在列表上,即检查是否存在list元素为true。)

现在,关系是自反的,显然是正确的。严格来说,不,a potato具有 a potato(并且在这里使用“ is”的意义上甚至都不是,例如“ A Cop is a Cop”),但这只是终止条件,涵盖了之后的所有关系沿着树走(与真正的不同,这意味着“朝着叶子”)。

在所有其他情况下,我们尝试从中提取一个元组knowledge(在进行filter编辑以确保仅看到与要检查的第一个元素相同的对后),然后从其指向的地方继续。列表理解处理所有可能的元组以继续进行,并verify在每种情况下再次调用。一个死胡同只会在这里有一个空列表并false整体返回,因此不会影响verify调用它的实例。


您能为非Haskell流利的人添加简短的解释吗?
J Atkin

愉快地!除非提出要求,否则我不会为每个帖子都这样做。
Leif Willerts 2015年

好,谢谢!(补白)
J Atkin

哇,这是一些解释。
J Atkin

2
我刚读完上半部分Learn you a haskell for great good!,现在我明白了!(这个答案实际上是促使我学习更多有关haskell和FP的知识,这真是太酷了!)
J Atkin

4

JavaScript中,265个 263字节

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

输入一个空白字符串以退出。

说明

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

你能用string.split(" ");吗?
J Atkin

@JAtkin我曾经.match(/\w+/g)从单词中删除标点符号。
user81655 2015年

我看到了,但是会不会.split(" ")更短或更缺少什么?(我不懂JavaScript)
J Atkin 2015年

@JAtkin如果使用的话,.split我还必须使用.slice(0,-1)(两次),因为它B is a A.将使(带有)B继承。A..
user81655

@JAtkin实际上,我刚刚发现split接受正则表达式,因此可以使用.split(/\W/)。感谢您让我查找!
user81655
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.