골프 나 An OOP!


26

골프 나 An OOP!

객체 지향 프로그래밍의 두 가지 중요한 구성 요소는 상속과 구성입니다. 함께 사용하면 문제를 해결하기 위해 간단하면서도 강력한 클래스 계층을 만들 수 있습니다. 당신의 임무는 클래스 계층에 대한 일련의 진술을 분석하고 계층에 관한 질문에 답변하는 것입니다.

입력

파일이나 표준 입력에서 읽은 클래스 계층 구조에 대한 일련의 진술과 질문 중 언어에 가장 적합한 것입니다. 파일 옵션을 사용하면 파일 이름이 코드의 첫 번째 인수 (함수 인수 또는 명령 행 인수 중 하나)로 전달됩니다. 형식은 다음과 같습니다.

<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에서 상속이 A, A상속되지 않습니다 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) 전체 리더 보드로 답변에서 리더 보드를 생성합니다.

답변이 표시되도록하려면 다음 마크 다운 템플릿을 사용하여 헤드 라인으로 답변을 시작하십시오.

## 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 Person. Person has a name.
Reto Koradi

아 .. 나는 그것을 놓쳤다.
J Atkin

한 번에 모든 입력을 받아야합니까, 아니면 대화식 콘솔처럼 한 줄씩 입력 할 수 있습니까? # 2이면 입력 값이 통계 인 경우에도 진실 / 거짓을 출력 할 수 있습니까?
J Atkin

@JAtkin 한 번에 또는 한 줄씩 선택하십시오. 그것이 진술이라면, 출력이 없어야합니다. 질문 만 답변을받습니다.
Mego

답변:


13

CJam, 59 바이트

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

이것은 두 테스트 사례 모두에 대해 즉시 완료됩니다.

질문의 두 번째 이름 1또는 0(진실한) 또는 (거짓)을 인쇄합니다.

CJam 통역사 에서 온라인으로 사용해보십시오 .

생각

클래스와 멤버의 차이로 인해 입력이 부분 정의를 제공하는 프리오더 를 작성해야합니다 .

우리는되도록 정의 XY IFF X 것은 A는 y는 또는 XY를 .

첫 번째 테스트 사례의 경우 입력에 BA , CBAfoo가 표시 됩니다. 때문에 이행 성, 우리는 또한이 Bfoo는 , C ≺ 및 ≺ foo는 . 또한, 반사율로 인해 xx 는 항상 참입니다.

주어진 입력에 대해, 우리는 진술에서 ≺의 부분적 정의를 추출하고 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
CJam에 클래스가 없다는 점을 고려하면 인상적입니다. D
Beta Decay

이것은 아름답다.
Mego

@BetaDecay 클래스는 본질적으로 중첩 된 세트입니다. 수업은 모든 언어로 구현됩니다. 첫 번째 예에서 말하십시오. C:{B:{A:{foo:{}}}}
A̲̲

8

파이썬 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)하고 전달하십시오 f. 실제로, 당신은 전혀 필요하지 않습니다 h(z)-당신이 그것을 부르는 곳에 몸을 두십시오. 가 아닌 쿼리에 대해 잘못된 값을 출력해야하므로을 필요로 하지 않고을 사용 r=2하지 print(r)않아도 if됩니다. 몇 바이트로 이름 syn을 바꾸고 z삭제할 수 있습니다 . 나는 당신 []이 첫 번째 목록의 이해 를 필요로하지 않는다고 생각합니다 any.
Mego

또한 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 와우, 모든 팁을 주셔서 감사합니다. 나중에 넣어야합니다.
J Atkin

이 게시물 은 아마 많은 도움 될 것입니다.
Mego

@ Mego Big 감사합니다. 이제 396으로 줄었습니다. 곧 게시하겠습니다.
J Atkin

4

하스켈, 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. x그리고 v( '추출'과 '확인') 접두어가 접두어를 만드는 것보다 잘리는 지 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이에 각 단어 목록의 꺼낸다 우리가 정말 할 요소는 n(문장의 첫 번째 단어입니다 - 그래서 일 하나 n == 0, 질문의 두 번째 단어입니다 - 그래서 n == 1)를 사용하여 !!연산자와 마지막을, 어떤에서 우리 를 사용하여 마지막 문자 ( '.'또는 '?') 를 잘라야합니다 init.

(나는 클래스와 멤버 사이의 구별을 완전히 무시하기 때문에 대문자를 완전히 무시한다는 점에 유의하십시오. 멤버는 지식 기반에 의해 구성된 트리의 리프 일뿐입니다. (그러나 모든 리프가 멤버를 나타내는 것은 아니며 서브 클래스도 멤버도없는 클래스 일 수도 있습니다.) ) (모든 하위 노드가 상위 노드가 나타내는 하위 클래스 또는 멤버를 나타냄) OP가 적용되지 않는 경우이 방법을 잘못 수정했습니다. 곧 솔루션을 수정하겠습니다.)

이제, map (extract 0) knowledgemap (extract 1) questionssubclass- 또는 초 내지 제 부재-관계를 나타내는 이름 튜플리스트이다.

튜플 map (extract 0) knowledge은 모두 진정한 관계이며, 이제 튜플 은 첫 번째 인수가로 설정되어 함수에 map (extract 1) questions매핑 verify됩니다 map (extract 0) knowledge.

(지금부터 내부에 verify, knowledge매개 변수 이름 및 이미 지칭 extract에드 튜플리스트).

(또한, 판독시 verify의 상태 유의 ||우아 LINEBREAK 후 ()는 SE 가로 스크롤을 피하기는 '재귀'과 '순환'케이스 사이 통상 부울 분리는, or그리스트를 통해, 즉 검사 폴드있는 경우 list 요소가 true입니다.)

자, 관계가 재귀 적이라면 분명히 맞습니다. 엄밀히 아니,이 말하기 potato하지 않는 potato(그리고 같이도 여기에 사용되는 감각 '이다'에서 하나가 아닌 'A 경찰은 경찰이다'),하지만 그냥 종료 조건의 그 커버 모든 관계 후 나무를 걷다 (실제 나무 의 경우와 달리 '잎을 향하여'를 의미).

다른 모든 경우에, 우리는 튜플을 가져 와서 knowledge( filter확인하려는 것과 동일한 첫 번째 요소와 쌍 만 '보고'확인하기 위해 노력한 후 ) 시작점에서 시작합니다. 리스트 이해는 가능한 모든 튜플을 처리 verify하고 각 경우에 다시 호출 합니다. 막 다른 골목은 여기에 빈 목록을 가지고 false전체를 반환 하므로 verify호출 한 인스턴스에 영향을 미치지 않습니다 .


하스켈에 능숙하지 않은 사람들에 대한 간단한 설명을 추가해 주시겠습니까?
J Atkin

행복하게! 요청 될 때까지 모든 게시물에 대해하지 않습니다.
Leif Willerts

알았어 고마워! (필러)
J 앳킨

와우, 그게 몇 가지 설명입니다.
J Atkin

2
나는 방금 전반부를 읽었으며 Learn you a haskell for great good!이제 이것을 이해합니다! (이 답변은 실제로 하스켈과 FP에 대해 더 많이 알게 된 계기가되었으며 sooooo cool입니다!)
J Atkin

4

자바 스크립트, 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

나는 그것을 보았지만 .split(" ")더 짧지 않거나 무언가를 놓치고 있습니까? (나는 자바 스크립트를 모른다)
J Atkin

@JAtkin 만약 내가 사용 .split나는 또한 사용해야 .slice(0,-1)하기 때문에 (2 회) B is a A.만들 것 B상속 A.합니다 (로 .).
user81655

@JAtkin 사실 split은 정규 표현식을 받아들이므로 사용할 수 있다는 것을 알았습니다 .split(/\W/). 내가 찾게 해줘서 고마워!
user81655
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.