My Pet Peeve Challenge

5

2

There's something (well, many things ) that really annoys me. It is when dictionaries (English, not Pythonic) use the defining word itself to define the word, also called circular definitions. Example:

reticence: the quality of being reticent

-- Apple Dictionary

Circular definition: a definition that is circular

-- Wikipedia (in jest)

Anyway,

Challenge

You are given a set of dictionary definitions. Your program should output the number of circular definitions in the input. As usual, code golf, lowest bytes wins, no standard loopholes, yada yada.

Input

Input can be in any reasonable form, including:

  • A dictionary (oh, the irony)
  • A list of strings
  • Line-by-line input, from STDIN or equivalent

You will be given the defined word (it is a single word without spaces) and its definition, possibly containing the defined word itself.

Circular definitions?

A definition is circular for the purposes of this challenge if it satisfies one of the following conditions:

  • The definition contains the defined word
  • The definition contains the defined word minus one of these suffixes:
    • -ing
    • -ed
    • -ly
  • The definition contains the defined word plus one of the above suffixes

Output

You should output an integer stating the number of circular definitions in the input. If there are none, you can output zero, a falsy, or a nully.

Good luck!

Leaderboards

Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

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

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

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

You can also make the language name a link which will then show up in the leaderboard snippet:

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

/* Configuration */

var QUESTION_ID = 100007; // Obtain this from the url
// It will be likes://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 47670; // This should be the user ID of the challenge author.

/* App */

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,]*[^\s,]),.*?(\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,
      });
    
  });
  
  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;
    if (/<a/.test(lang)) lang = jQuery(lang).text();
    
    languages[lang] = languages[lang] || {lang: a.language, 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 > b.lang) return 1;
    if (a.lang < b.lang) 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);
  }

}
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;
}
<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="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>
<div id="language-list">
  <h2>Winners 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>
<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>

OldBunny2800

Posted 2016-11-16T01:50:23.753

Reputation: 1 379

Wow, 100007! Is ID counting network wide or site wide? – OldBunny2800 – 2016-11-16T01:51:14.400

4It's ironic (adj: using or characterized by irony) that your first example definition (reticence) would not count as circular by your rules ;) – Geobits – 2016-11-16T02:01:42.623

4The count is site-wide. We reached 100,000 posts just an hour ago :-) If it was network-wide, we'd be around 50 million... – ETHproductions – 2016-11-16T02:02:30.877

Yeah... just trying to simplify things a bit @Geobits! – OldBunny2800 – 2016-11-16T02:02:50.460

I don't believe the second example definition (Circular definition) counts as circular either, unless you want a much more complex level of language processing than the question implies... – DLosc – 2016-11-16T02:05:50.697

On a related note: 1) Do we have to worry about upper/lowercase? 2) Will there ever be spaces in defined "words"? – DLosc – 2016-11-16T02:07:22.773

@Dlosc, 1st: I simplified what constitutes a circular definition for the purposes of this challenge; that would have been a lot of suffixes and grammar rules to account for! I didn't even touch on prefixes. 2nd: 1) Words are case-insensitive; Hello is the same as hello. 2) No. – OldBunny2800 – 2016-11-16T02:09:43.967

Can I take the input as a list of lists? – BookOwl – 2016-11-17T13:50:22.613

Answers

2

Pyth, 28 bytes

Really want to condense the logic.

sm}hKm:k"(ing|ed|ly)$";cd;tK

Try it online here.

Maltysen

Posted 2016-11-16T01:50:23.753

Reputation: 25 023

Congrats! Good answer! – OldBunny2800 – 2016-11-16T04:27:29.057

["test - testing"] returns True – OldBunny2800 – 2016-11-22T00:03:44.093

1@OldBunny2800 oh, that's cuz True is 1 in python – Maltysen – 2016-11-22T00:04:42.043

OK then. I can't break it, and that's a good thing! – OldBunny2800 – 2016-11-22T00:05:23.043

0

Python, 187 185, self-disqualified!

EDIT: I've decided to disqualify this due to its bugginess, but its good for the pun.


Takes a Pythonic dictionary (hehe) and outputs the number to the console. This is quite buggy, though, should've done more tests...

def c(i):
 for k, v in i.items():
  l,c,t,y="",0,k[-2:],k[:-2]
  if t=="ed":l=y
  if t=="ly":l=y
  if k[-3:]=="ing":l=k[:-3]
  if" "+k+" "in v:c+=1
  if" "+l in v:c+=1
 print(c)

ender_scythe

Posted 2016-11-16T01:50:23.753

Reputation: 249

Nice! Quick answer. – OldBunny2800 – 2016-11-16T02:35:37.137

c({"a":"aed","bed":"b"}) returns 0, it should return 2. – OldBunny2800 – 2016-11-16T02:38:22.493

Golfed code, Python 2 only. Still as buggy as your current code, though :) – Erik the Outgolfer – 2016-11-17T18:11:26.150

I believe it's buggy because it treats each entry as a single word, so "c: ced." would break. It also doesn't check entries. – ender_scythe – 2016-11-17T22:56:29.193

0

Python, 129 bytes

Takes a list of two item lists where the first item is the word and the second is the definition. It returns the amount circular definitions it found.

def f(d,n=0):
 for k,v in d:k,v=k.lower(),v.lower();n+=any(k+_ in v or k.rstrip(_)in v for _ in("","ing","ed","ly"))
 return n

BookOwl

Posted 2016-11-16T01:50:23.753

Reputation: 291

What is the def f(d,n=0): part for? What is the input in n used for? – OldBunny2800 – 2016-11-17T19:59:14.270

1It creates the variable n and sets it to 0 in 1 less character than setting it on its own line. You don't pass a value for it. – BookOwl – 2016-11-21T18:04:25.560

Errors: f({"test":"testing","wondered":"wonder"}) -- ValueError: too many values to unpack, f({"a":"b","c":"d","e":"f"}) -- ValueError: need more than one value to unpack – OldBunny2800 – 2016-11-21T21:28:14.753

1It doesn't take a dictionary, it takes a list of two item lists like so: f([ ["test", "testing"], ["wondered", "wonder"] ]) – BookOwl – 2016-11-21T22:13:49.053

Would it be easier to use repeatable args? eg: def f(*d,n=0) Then you won't have to worry about the lists of a list thing. – OldBunny2800 – 2016-11-21T23:59:40.047

1But that would add a byte. – BookOwl – 2016-11-22T14:51:44.520