Golf Me An OOP!


26

Golf Me 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) ชื่อทั้งหมดเป็นกรณี ๆ - ไม่ได้เป็นระดับเดียวกับABC123Abc123

จะไม่มีการใด ๆ ที่เป็นมรดกของวัฏจักร - ถ้าBสืบทอดจากA, Aจะไม่ได้รับมรดกจากBหรือใด ๆ ของB's เด็ก

ชื่อคลาสเท่านั้นที่จะเป็นส่วนหนึ่งของลำดับชั้น - คำสั่งเช่น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
Criminal is a Person@JAtkin Person has a name.
Reto Koradi

อ่า ... ฉันพลาดไปแล้ว
J Atkin

ฉันจำเป็นต้องป้อนข้อมูลทั้งหมดในครั้งเดียวหรือฉันสามารถใช้ทีละบรรทัดเหมือนคอนโซลแบบโต้ตอบได้หรือไม่ ถ้า # 2 ฉันจะส่งออกความจริง \ falsey แม้ว่าการป้อนข้อมูลเป็น statment?
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เป็นปีหรือxมีY

สำหรับกรณีการทดสอบครั้งแรกรัฐการป้อนข้อมูลที่B ≺ , CBและ≺ foo เพราะกริยาเรายังมีBfoo , C ≺ และ≺ foo นอกจากนี้เนื่องจาก reflexivity, xxเป็นความจริงเสมอ

สำหรับอินพุตที่กำหนดเราสามารถแยกคำจำกัดความบางส่วนของ statements จากข้อความใช้ความไวแสงจำนวนเพียงพอเพื่อทำให้คำจำกัดความของ≺และตอบคำถามในที่สุด

รหัส

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 Classes เป็นชุดซ้อนกันเป็นหลัก ชั้นเรียนดำเนินการในทุกภาษา พูดในตัวอย่างแรก 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

ฉันลบคำสั่ง debug เพื่อความชัดเจนในโปรแกรมหลัก แต่ถ้าคุณต้องการที่จะเห็นพวกเขาเพียงแค่ดูในประวัติศาสตร์


แทนที่จะใช้global fใน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

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ให้สตริง ไม่แน่ใจว่าการสร้างxและv('แยก' และ 'ยืนยัน') ผสมจะตัดมากกว่าการทำmapมัดหรือถ้าเป็นไปได้

แก้ไข: คำอธิบาย

ดังนั้น(#)เป็นวิธีที่คุณกำหนดโอเปอเรเตอร์ infix ฉันใช้มันเป็นแบบย่อเพื่อmapใช้ฟังก์ชั่นกับองค์ประกอบแต่ละรายการ การแก้ไขปัญหานี้และนามแฝงอื่น ๆlหลีกเลี่ยง 'direct-function-application'-operator $และเพิ่มวงเล็บและระยะห่างออกไปมากขึ้นและด้วยชื่อฟังก์ชันที่แท้จริงเรามาถึง:

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 แบ่งรายการใน tuple ของส่วนแรกโดยไม่มีคำถาม (งบทั้งหมด) และส่วนหนึ่งจากคำถามแรกที่ (ทุกคำถาม)

mapping extract nเหล่านี้นำออกมาจากแต่ละคำรายการองค์ประกอบที่เราต้องการจริง ๆnหนึ่ง (ซึ่งในงบเป็นคำแรก - ดังนั้นn == 0และในคำถามคือคำที่สอง - ดังนั้นn == 1) โดยใช้!!ผู้ประกอบการและคนสุดท้ายที่เรา มีการตัดตัวอักษรสุดท้าย (อย่างใดอย่างหนึ่ง'.'หรือ'?') initโดยใช้

(โปรดทราบว่าฉันเพิกเฉยต่อการใช้อักษรตัวพิมพ์ใหญ่อย่างสมบูรณ์นั่นเป็นเพราะฉันไม่สนใจความแตกต่างระหว่างชั้นเรียนและสมาชิกอย่างสมบูรณ์สมาชิกเป็นเพียงใบไม้ของต้นไม้ที่สร้างขึ้นโดยฐานความรู้ (แต่ไม่ใช่ใบไม้ทั้งหมดเป็นตัวแทนสมาชิกพวกเขาอาจเป็นคลาสที่ไม่มีคลาสย่อยหรือสมาชิก ) ซึ่งโหนดย่อยทุกโหนดแสดงถึงคลาสย่อยหรือสมาชิกของโหนดแม่ที่เป็นตัวแทนฉันเพียงแค่คิดว่านี่เป็นสิ่งที่ไม่ถูกต้องในกรณีที่ไม่ครอบคลุมโดย OP จะแก้ไขวิธีแก้ปัญหาในไม่ช้า)

ตอนนี้map (extract 0) knowledgeและmap (extract 1) questionsเป็นรายการของ tuples ของชื่อที่แสดงถึง subclass- หรือความสัมพันธ์ของสมาชิกของที่หนึ่งถึงสอง

tuples ในmap (extract 0) knowledgeความสัมพันธ์ที่แท้จริงที่อยู่ในmap (extract 1) questionsแมปตอนนี้ฟังก์ชั่นมากกว่าด้วยชุดอาร์กิวเมนต์แรกverifymap (extract 0) knowledge

(จากนี้ไปภายในverify, knowledgeเป็นชื่อพารามิเตอร์และหมายถึงที่มีอยู่แล้วextractในรายการ tuple ed.)

(นอกจากนี้เมื่ออ่านverifyโปรดทราบว่าในขณะที่||(หลังจากการเรียงลำดับที่ไม่เหมาะสมเพื่อหลีกเลี่ยงการเลื่อนแนวนอนบน SE) เป็นความผิดปกติทางบูลีนระหว่าง 'reflexive' และ 'recursive' กรณีorที่มีอยู่ในรายการเช่นตรวจสอบว่ามีหรือไม่ องค์ประกอบรายการเป็นจริง)

ตอนนี้ความสัมพันธ์นั้นถูกต้องถ้ามันสะท้อนกลับ อย่างเคร่งครัดพูดไม่เป็นpotatoไม่ได้มีpotato (และมันไม่ได้แม้แต่คนเดียวในความรู้สึก 'เป็น' จะใช้ที่นี่ในขณะที่ 'A ตำรวจเป็นตำรวจ') แต่นั่นเป็นเพียงเงื่อนไขการเลิกจ้างที่ครอบคลุมทุกความสัมพันธ์หลังจากที่ เดินลงต้นไม้ (ซึ่งไม่เหมือนในกรณีของต้นไม้จริงหมายถึง 'ไปทางใบไม้')

ในกรณีอื่น ๆ ทั้งหมดเราพยายามดึง tuple จากknowledge(หลังจากที่เราfilterแก้ไขเพื่อให้แน่ใจว่าเราเห็นคู่เท่านั้นที่มีองค์ประกอบแรกเหมือนกับที่เราต้องการตรวจสอบ) และดำเนินการต่อจากจุดที่ชี้ไป ความเข้าใจในรายการเกี่ยวข้องกับสิ่งอันดับที่เป็นไปได้ทั้งหมดเพื่อดำเนินการต่อและโทรverifyอีกครั้งในแต่ละกรณี ปลายตายจะมีรายการว่างเปล่าที่นี่และกลับมาfalseโดยรวมดังนั้นจึงไม่มีผลต่ออินสแตนซ์ของverifyมันที่ถูกเรียกโดย


คุณสามารถเพิ่มคำอธิบายสั้น ๆ สำหรับคนที่ไม่เก่งได้อย่างไร
J Atkin

อย่างมีความสุข! ฉันไม่ได้ทำทุกโพสต์จนกว่าจะมีการร้องขอ
Leif Willerts

โอเคขอบคุณ! (filler)
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

ฉันเห็นสิ่งนั้น แต่จะไม่.split(" ")สั้นลงหรือฉันขาดอะไรไป? (ฉันไม่รู้จาวาสคริปต์)
J Atkin

@JAtkin ถ้าฉันใช้.splitฉันก็จะต้องใช้.slice(0,-1)(สองครั้ง) เพราะB is a A.จะทำให้BสืบทอดA.(กับ.)
user81655

@JAtkin .split(/\W/)ที่จริงฉันก็พบว่าแยกยอมรับการแสดงออกปกติดังนั้นฉันสามารถใช้ ขอบคุณที่ทำให้ฉันดูมัน!
user81655
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.