Golf Me An OOP!

26

Golf Me An OOP!

Dua komponen penting dari pemrograman berorientasi objek adalah pewarisan dan komposisi. Bersama-sama, mereka memungkinkan untuk menciptakan hierarki kelas yang sederhana namun kuat untuk menyelesaikan masalah. Tugas Anda adalah mengurai serangkaian pernyataan tentang hierarki kelas, dan menjawab pertanyaan tentang hierarki.

Memasukkan

Serangkaian pernyataan dan pertanyaan tentang hierarki kelas, baca dari file atau input standar, mana yang terbaik untuk bahasa Anda. Jika Anda menggunakan opsi file, nama file akan diteruskan sebagai argumen pertama ke kode Anda (argumen fungsi atau argumen baris perintah, mana pun yang Anda pilih). Formatnya adalah sebagai berikut:

<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

Masukan akan selalu berupa pernyataan, lalu pertanyaan. Semua nama kelas akan dimulai dengan huruf bahasa Inggris huruf besar ( A-Z), dan semua nama anggota akan dimulai dengan huruf bahasa Inggris huruf kecil ( a-z). Semua nama peka terhadap huruf besar-kecil - ABC123tidak sama dengan kelas Abc123.

Tidak akan ada warisan siklus - jika Bmewarisi dari A, Atidak akan mewarisi dari Batau dari Banak-anak.

Hanya nama kelas yang akan menjadi bagian dari hierarki - pernyataan seperti foo is a bar.atau document has a name.tidak akan muncul.

Keluaran

Serangkaian nilai kebenaran atau kesalahan, sebagai jawaban atas pertanyaan, ditulis ke output standar atau sebagai nilai pengembalian fungsi Anda. Jika Anda tidak memiliki informasi yang cukup untuk menjawab pertanyaan (mis. Pertanyaan yang melibatkan nama yang belum Anda lihat dalam pernyataan), jawab dengan nilai falsey.

Uji Kasus

Kasus 1:

Memasukkan:

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?

Keluaran:

True
True
False

Kasus 2:

Memasukkan:

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?

Keluaran:

True
True
False
False
True

Aturan

  • Anda dapat menjawab dengan fungsi atau program
  • Celah standar dilarang
  • Ini adalah , jadi jawaban terpendek yang benar dalam byte menang
  • Jawaban yang menang akan dipilih dalam satu minggu

Semoga beruntung, dan semoga OOP itu menyertai Anda!

Papan peringkat

Cuplikan Stack di bagian bawah posting ini menghasilkan leaderboard dari jawaban a) sebagai daftar solusi terpendek per bahasa dan b) sebagai leaderboard keseluruhan.

Untuk memastikan bahwa jawaban Anda muncul, silakan mulai jawaban Anda dengan tajuk utama, menggunakan templat Penurunan harga berikut:

## Language Name, N bytes

di mana Nukuran kiriman Anda. Jika Anda meningkatkan skor Anda, Anda dapat menyimpan skor lama di headline, dengan mencoretnya. Contohnya:

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

Jika Anda ingin memasukkan beberapa angka dalam tajuk Anda (mis. Karena skor Anda adalah jumlah dari dua file atau Anda ingin membuat daftar hukuman penterjemah secara terpisah), pastikan bahwa skor sebenarnya adalah angka terakhir di tajuk:

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

Anda juga dapat membuat nama bahasa menjadi tautan yang kemudian akan muncul di cuplikan:

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

Mego
sumber
Bagaimana dengan Does Criminal have a name?setara True? Apakah semua benda memiliki nama?
J Atkin
4
@JAtkin Criminal is a Person. Person has a name.
Reto Koradi
Ahh ... aku melewatkan itu.
J Atkin
Apakah saya perlu mengambil semua input sekaligus, atau dapatkah saya mengambilnya baris demi baris seperti konsol interaktif? Jika # 2, dapatkah saya menghasilkan kebenaran \ falsey bahkan jika inputnya adalah statment?
J Atkin
@JAtkin Sekaligus atau baris demi baris, pilihan Anda. Jika itu pernyataan, seharusnya tidak ada output. Hanya pertanyaan yang mendapat jawaban.
Mego

Jawaban:

13

CJam, 59 byte

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

Ini selesai secara instan untuk kedua kasus uji.

Entah itu mencetak nama nama kedua dari pertanyaan atau 1(keduanya benar), atau 0(salah).

Cobalah online di juru bahasa CJam .

Ide

Karena perbedaan antara kelas dan anggota, tantangan bermuara pada menciptakan preorder yang inputnya memberikan definisi parsial.

Kami mendefinisikan bahwa xy jika x adalah y atau x memiliki y .

Untuk kasus uji pertama, input menyatakan bahwa BA , CB, dan Afoo . Karena transitivitas, kami juga memiliki Bfoo , CA dan Afoo . Juga, karena refleksivitas, xx selalu benar.

Untuk input yang diberikan, kita dapat mengekstraksi definisi parsial ≺ dari pernyataan, menerapkan transitivitas dalam jumlah yang cukup untuk melengkapi definisi ≺ dan akhirnya menjawab pertanyaan.

Kode

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#
Dennis
sumber
2
Ini mengesankan mengingat CJam tidak memiliki kelas: D
Beta Decay
Ini indah.
Mego
@BetaDecay Classes pada dasarnya adalah kumpulan bersarang; kelas diimplementasikan dalam setiap bahasa. Katakan dalam contoh pertama. 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)

Ini adalah versi lengkap dengan komentar

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)

Output untuk test case # 1:

True
True
False

Kasus # 2:

True
True
False
False
True

Saya menghapus perintah debug untuk kejelasan dalam program utama, tetapi jika Anda ingin melihatnya lihat saja di histori

J Atkin
sumber
Alih-alih menggunakan global fdi h(z), penggunaan def h(z,f)dan lulus global fdi saat memanggil itu. Bahkan, Anda tidak perlu h(z)sama sekali - cukup letakkan tubuh di tempat Anda menyebutnya. Anda tidak perlu r=2, dan Anda bisa melakukannya print(r)tanpa if, karena Anda perlu menampilkan nilai falsey untuk kueri palsu. Anda dapat mengubah nama synmenjadi zdan mencukur beberapa byte di sana. Saya pikir Anda tidak perlu []memahami daftar Anda terlebih dahulu any.
Mego
Anda juga menggunakan esekali, sehingga Anda bisa menghilangkan definisi dan hanya menggunakan [a,b,c,d]. Alih-alih if s(i,g) is not None, lakukan if s(i,g)- re.Matchbenda selalu dievaluasi untuk Truejika kecocokan ditemukan. Anda juga dapat menjatuhkan 2 byte dengan f[x]+=f[y].
Mego
@Mego Wow, terima kasih atas semua tipsnya. Saya harus memasukkannya nanti.
J Atkin
Posting ini mungkin akan banyak membantu Anda
Mego
@Mego Besar, terima kasih, sudah 396 sekarang. Saya akan posting sebentar lagi.
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

Berikan string ke o. Tidak yakin apakah membuat xdan v('mengekstrak' dan 'memverifikasi') infiks memotong lebih dari membuat mapinfiks, atau jika keduanya memungkinkan.

EDIT: Penjelasan

Jadi, (#)adalah bagaimana Anda mendefinisikan operator infiks, saya menggunakannya hanya sebagai singkatan untuk map, menerapkan fungsi ke setiap elemen daftar. Mengatasi ini dan alias lainnya l, menghindari operator 'fungsi-aplikasi-langsung' $dan menambahkan lebih banyak tanda kurung dan menghapus hal-hal, dan dengan nama fungsi sebenarnya kami tiba di:

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) adalah daftar daftar kata dari setiap baris dalam string input.

(=='?').last.last adalah predikat yang menunjukkan apakah huruf terakhir pada kata terakhir dari sebuah baris adalah tanda tanya, yaitu apakah baris tersebut adalah sebuah pertanyaan.

break memecah daftar menjadi dua bagian pertama tanpa pertanyaan (semua pernyataan) dan bagian dari pertanyaan pertama (semua pertanyaan).

mapping extract npada ini mengambil dari setiap kata daftar elemen yang kita inginkan, yang npertama (yang dalam pernyataan adalah kata pertama - jadi n == 0, dan dalam pertanyaan adalah kata kedua - jadi n == 1) menggunakan !!operator dan yang terakhir, dari mana kita harus memotong huruf terakhir (salah satu '.'atau '?') menggunakan init.

(Perhatikan bahwa saya sepenuhnya mengabaikan huruf besar, itu karena saya benar-benar mengabaikan perbedaan antara kelas dan anggota, anggota hanya daun pohon yang dibangun oleh basis pengetahuan (tetapi tidak semua daun mewakili anggota, mereka juga mungkin kelas tanpa subkelas atau anggota) ), di mana setiap simpul anak mewakili subkelas atau anggota dari apa yang simpul induknya wakili. SAYA HANYA MENYADARI HAL INI SALAH YANG PERLU DILAKUKAN dalam kasus-kasus yang tidak dicakup oleh OP. Akan segera mengedit solusi.)

Sekarang, map (extract 0) knowledgedan map (extract 1) questionsadalah daftar tupel nama yang mewakili hubungan sub-kelas atau anggota dari yang pertama hingga yang kedua.

Semua tuple dalam map (extract 0) knowledgesemua hubungan yang benar, map (extract 1) questionsyang sekarang dipetakan verifyfungsinya, dengan argumen pertama ditetapkan map (extract 0) knowledge.

(Mulai sekarang, di dalam verify, knowledgeadalah nama parameter dan merujuk ke extractdaftar tuple yang sudah diedit.)

(Juga, saat membaca verify, perhatikan bahwa sementara ||(setelah linebreak yang tidak tepat untuk menghindari gulir horizontal pada SE) adalah disfungsi boolean yang normal antara case 'refleksif' dan 'rekursif', orlipatan yang ada pada daftar, yaitu memeriksa apakah ada elemen daftar benar.)

Sekarang, suatu hubungan jelas benar jika itu refleksif. Sebenarnya, tidak ada, seorang potatotidak memiliki sebuah potato(dan bahkan tidak satu dalam arti 'adalah' digunakan di sini, seperti dalam 'A Cop adalah Cop'), tapi itu hanya kondisi terminasi yang mencakup semua hubungan setelah berjalan menyusuri pohon (yang tidak seperti pohon nyata berarti 'menuju daun').

Dalam semua kasus lain, kami mencoba mengambil tupel dari knowledge(setelah kami filtermenyunting untuk memastikan bahwa kami 'melihat' hanya pasangan dengan elemen pertama yang sama dengan yang ingin kami periksa), dan melanjutkan dari tempat itu menunjuk. Pemahaman daftar berkaitan dengan semua kemungkinan tuple untuk melanjutkan dan menelepon verifylagi dalam setiap kasus. Jalan buntu hanya akan memiliki daftar kosong di sini dan kembali falsesecara keseluruhan, sehingga tidak mempengaruhi turunannya verify.

Leif Willerts
sumber
Bisakah Anda menambahkan penjelasan singkat untuk orang yang tidak lancar berbicara?
J Atkin
Dengan senang hati! Saya hanya tidak melakukannya untuk setiap posting sampai diminta.
Leif Willerts
Ok terima kasih! (pengisi)
J Atkin
Wow, itu penjelasannya.
J Atkin
2
Saya baru saja selesai membaca paruh pertama Learn you a haskell for great good!dan ini sekarang saya mengerti ini! (Jawaban ini sebenarnya yang mendorong saya untuk mempelajari lebih lanjut tentang haskell dan FP, dan itu sangat keren!)
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)))

Masukkan string kosong untuk berhenti.

Penjelasan

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)
    )
  )
pengguna81655
sumber
Bisakah Anda menggunakan string.split(" ");?
J Atkin
@ AJtkin saya digunakan .match(/\w+/g)untuk menghapus tanda baca dari kata-kata.
user81655
Saya melihat itu, tetapi tidak .split(" ")akan lebih pendek atau apakah saya melewatkan sesuatu? (Saya tidak tahu javascript)
J Atkin
@ Jtkin Jika saya menggunakan .splitsaya juga harus menggunakan .slice(0,-1)(dua kali) karena B is a A.akan membuat Bwarisan A.(dengan .).
user81655
@JAtkin Sebenarnya saya baru tahu bahwa split menerima ekspresi reguler sehingga saya bisa menggunakannya .split(/\W/). Terima kasih telah membuat saya mencari itu!
user81655