Golf-me um OOP!
Dois componentes importantes da programação orientada a objetos são herança e composição. Juntos, eles permitem criar hierarquias de classe simples e poderosas para resolver problemas. Sua tarefa é analisar uma série de instruções sobre uma hierarquia de classes e responder a perguntas sobre a hierarquia.
Entrada
Uma série de declarações e perguntas sobre uma hierarquia de classes, lida em um arquivo ou entrada padrão, o que for melhor para o seu idioma. Se você usar a opção de arquivo, o nome do arquivo será passado como o primeiro argumento para o seu código (argumento da função ou argumento da linha de comando, o que você escolher). O formato é o seguinte:
<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 entrada será sempre declarações, depois perguntas. Todos os nomes de turma começarão com uma letra maiúscula em inglês ( A-Z
) e todos os nomes de membros começarão com uma letra minúscula em inglês ( a-z
). Todos os nomes diferenciam maiúsculas de minúsculas - ABC123
não são da mesma classe que Abc123
.
Não haverá herança cíclica - se B
herdar de A
, A
não herdará de B
ou qualquer um dos B
filhos.
Somente nomes de classe farão parte de uma hierarquia - instruções como foo is a bar.
ou document has a name.
não ocorrerão.
Saída
Uma série de valores verdadeiros ou falsos, como respostas às consultas, gravadas na saída padrão ou como o valor de retorno da sua função. Se você não tiver informações suficientes para responder a uma pergunta (por exemplo, perguntas que envolvam nomes que você não viu nas declarações), responda com um valor falsey.
Casos de teste
Caso 1:
Entrada:
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?
Saída:
True
True
False
Caso 2:
Entrada:
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?
Saída:
True
True
False
False
True
Regras
- Você pode responder com uma função ou um programa
- As brechas padrão são proibidas
- Isso é código-golfe , então a resposta correta mais curta em bytes ganha
- A resposta vencedora será escolhida em uma semana
Boa sorte, e que o OOP esteja com você!
Entre os melhores
O snippet de pilha na parte inferior desta postagem gera o cabeçalho das respostas a) como uma lista da solução mais curta por idioma eb) como um cabeçalho geral.
Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:
## Language Name, N bytes
onde N
está o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:
## Ruby, <s>104</s> <s>101</s> 96 bytes
Se você quiser incluir vários números no cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou você deseja listar as penalidades do sinalizador de intérpretes separadamente), verifique se a pontuação real é o último número no cabeçalho:
## Perl, 43 + 2 (-p flag) = 45 bytes
Você também pode transformar o nome do idioma em um link que será exibido no snippet:
## [><>](http://esolangs.org/wiki/Fish), 121 bytes
<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 290px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 61097; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 45941; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>
Does Criminal have a name?
igual aTrue
? Todos os objetos têm um nome?Criminal is a Person
.Person has a name
.Respostas:
CJam, 59 bytes
Isso termina instantaneamente nos dois casos de teste.
Ou imprime o segundo nome da pergunta ou
1
(ambos de verdade) ou0
(falso).Experimente on-line no intérprete CJam .
Idéia
Devido à distinção entre classes e membros, o desafio se resume a criar uma pré - encomenda para a qual a entrada fornece uma definição parcial.
Definimos que x ≺ y se x é um y ou x tem um y .
Para o primeiro caso de teste, a entrada indica que B ≺ A , C ≺ B e A ≺ foo . Por causa da transitividade, também temos B ≺ foo , C ≺ A e A ≺ foo . Além disso, devido à reflexividade, x ≺ x é sempre verdade.
Para uma determinada entrada, podemos extrair a definição parcial de ≺ das declarações, aplicar transitividade por um número suficiente de vezes para concluir a definição de ≺ e finalmente responder às perguntas.
Código
fonte
C:{B:{A:{foo:{}}}}
Python 3,
431331308 bytesEsta é a versão completa com comentários
Saída para o caso de teste nº 1:
Caso 2:
Eu removi os comandos debug para maior clareza no programa principal, mas se você gostaria de vê-los, basta olhar no histórico
fonte
global f
emh(z)
, usodef h(z,f)
e passar o mundialf
em quando chamá-lo. Na verdade, você não precisa deh(z)
nada - basta colocar o corpo onde você o chama. Você não precisar=2
, e pode simplesmente ficarprint(r)
sem oif
, pois precisa gerar um valor falsey para consultas falsas. Você pode renomearsyn
az
e raspar vários bytes lá. Não acho que você precise da[]
compreensão da sua lista no começoany
.e
uma vez, para poder eliminar a definição e apenas usá-la[a,b,c,d]
. Em vez deif s(i,g) is not None
, objetos doif s(i,g)
-re.Match
são sempre avaliadosTrue
se uma correspondência for encontrada. Você também pode soltar 2 bytes comf[x]+=f[y]
.Haskell, 157 bytes
Dê a string para
o
. Não tenho certeza se criarx
ev
('extrair' e 'verificar') infixes é mais do que criarmap
um infixo ou se ambos são possíveis.EDIT: Explicação
Então,
(#)
é assim que você define um operador infix, eu o uso apenas como uma abreviação demap
, aplicando uma função a cada elemento de uma lista. Resolvendo esse e o outro aliasl
, evitando o operador 'aplicativo de função direta'$
e adicionando ainda mais parênteses e espaçando as coisas, e com nomes de funções reais, chegamos a:map words (lines string)
é uma lista de listas de palavras de cada linha na sequência de entrada.(=='?').last.last
é um predicado indicando se a última letra da última palavra de uma linha é um ponto de interrogação, ou seja, se a linha é uma pergunta.break
quebra a lista em uma tupla da primeira parte sem perguntas (todas as declarações) e a parte da primeira pergunta em (todas as perguntas).map
pingarextract n
isso tira de cada palavra a lista dos elementos que realmente queremos, on
th (que em declarações é a primeira palavra - en == 0
, em perguntas, a segunda palavra - son == 1
) usando o!!
operador e o último, a partir do qual nós tem que cortar a última letra ('.'
ou'?'
) usandoinit
.(Observe que eu ignoro completamente a capitalização, é porque ignoro completamente a distinção entre classes e membros, os membros são apenas folhas de uma árvore construída pela base de conhecimento (mas nem todas as folhas representam membros, elas também podem ser classes sem subclasses nem membros ), na qual cada nó filho representa uma subclasse ou membro do que o nó pai representa. Eu percebi que isso é uma coisa errada a fazer nos casos não cobertos pelo OP. Editará a solução em breve.)
Agora,
map (extract 0) knowledge
emap (extract 1) questions
são listas de tuplas de nomes que representam um relacionamento de subclasse ou membro do primeiro ao segundo.As tuplas em
map (extract 0) knowledge
são todos os relacionamentos verdadeiros, aqueles emmap (extract 1) questions
agora são mapeados para averify
função, com o primeiro argumento definido comomap (extract 0) knowledge
.(A partir de agora, dentro
verify
,knowledge
é um nome de parâmetro e se refere àextract
lista de tuplas já editada.)(Além disso, ao ler
verify
, observe que, embora o||
(após a quebra de linha deselegante para evitar rolagem horizontal no SE) seja uma disjunção booleana normal entre o caso 'reflexivo' e o 'recursivo',or
dobra-o sobre uma lista, ou seja, verifica se há algum O elemento da lista é verdadeiro.)Agora, uma relação está obviamente correta se for reflexiva. Estritamente falando, não, a
potato
não possui umpotato
(e nem sequer um no sentido 'é' é usado aqui, como em 'Um policial é um policial'), mas essa é apenas a condição de término que cobre todos os relacionamentos após andar pela árvore (o que, diferentemente das árvores reais , significa "em direção às folhas").Em todos os outros casos, tentamos extrair uma tupla
knowledge
(depois de termosfilter
editado para ter certeza de que "vemos" apenas pares com o mesmo primeiro elemento que queremos verificar) e prosseguimos de onde ela aponta. A compreensão da lista lida com todas as tuplas possíveis para continuar e chamaverify
novamente em cada caso. Um beco sem saída terá apenas uma lista vazia aqui e retornará emfalse
geral, e assim não influenciará a instância daverify
qual foi chamada.fonte
Learn you a haskell for great good!
e agora eu entendo isso! (Esta resposta é, na verdade, o que me levou a aprender mais sobre Haskell e FP, e é muuuito legal!)JavaScript,
265263 bytesDigite uma sequência em branco para sair.
Explicação
fonte
string.split(" ");
?.match(/\w+/g)
remover a pontuação das palavras..split(" ")
seria mais curto ou estou perdendo alguma coisa? (Eu não sei javascript).split
eu também teria que usar.slice(0,-1)
(duas vezes) porqueB is a A.
fariaB
herdarA.
(com o.
)..split(/\W/)
. Obrigado por me fazer procurar isso!