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)



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 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


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!


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() {
    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+/);
        answers_hash[id] = a;
      if (!data.has_more) more_answers = false;
      comment_page = 1;

function getComments() {
    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)
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();


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) {
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    var match = body.match(SCORE_REG);
    if (match)
        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;
    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);

    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.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);

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">
  <table class="answer-list">
    <tbody id="answers">

<div id="language-list">
  <h2>Winners by Language</h2>
  <table class="language-list">
    <tbody id="languages">

<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>
<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>

  • \$\begingroup\$ Wow, 100007! Is ID counting network wide or site wide? \$\endgroup\$
    – AAM111
    Commented Nov 16, 2016 at 1:51
  • 4
    \$\begingroup\$ It's ironic (adj: using or characterized by irony) that your first example definition (reticence) would not count as circular by your rules ;) \$\endgroup\$
    – Geobits
    Commented Nov 16, 2016 at 2:01
  • 4
    \$\begingroup\$ The count is site-wide. We reached 100,000 posts just an hour ago :-) If it was network-wide, we'd be around 50 million... \$\endgroup\$ Commented Nov 16, 2016 at 2:02
  • \$\begingroup\$ Yeah... just trying to simplify things a bit @Geobits! \$\endgroup\$
    – AAM111
    Commented Nov 16, 2016 at 2:02
  • \$\begingroup\$ 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... \$\endgroup\$
    – DLosc
    Commented Nov 16, 2016 at 2:05

3 Answers 3


Pyth, 28 bytes

Really want to condense the logic.


Try it online here.

  • \$\begingroup\$ Congrats! Good answer! \$\endgroup\$
    – AAM111
    Commented Nov 16, 2016 at 4:27
  • \$\begingroup\$ ["test - testing"] returns True \$\endgroup\$
    – AAM111
    Commented Nov 22, 2016 at 0:03
  • 1
    \$\begingroup\$ @OldBunny2800 oh, that's cuz True is 1 in python \$\endgroup\$
    – Maltysen
    Commented Nov 22, 2016 at 0:04
  • \$\begingroup\$ OK then. I can't break it, and that's a good thing! \$\endgroup\$
    – AAM111
    Commented Nov 22, 2016 at 0:05

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():
  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
  • \$\begingroup\$ Nice! Quick answer. \$\endgroup\$
    – AAM111
    Commented Nov 16, 2016 at 2:35
  • \$\begingroup\$ c({"a":"aed","bed":"b"}) returns 0, it should return 2. \$\endgroup\$
    – AAM111
    Commented Nov 16, 2016 at 2:38
  • \$\begingroup\$ Golfed code, Python 2 only. Still as buggy as your current code, though :) \$\endgroup\$ Commented Nov 17, 2016 at 18:11
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Nov 17, 2016 at 22:56

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
  • \$\begingroup\$ What is the def f(d,n=0): part for? What is the input in n used for? \$\endgroup\$
    – AAM111
    Commented Nov 17, 2016 at 19:59
  • 1
    \$\begingroup\$ It 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. \$\endgroup\$
    – BookOwl
    Commented Nov 21, 2016 at 18:04
  • \$\begingroup\$ 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 \$\endgroup\$
    – AAM111
    Commented Nov 21, 2016 at 21:28
  • 1
    \$\begingroup\$ It doesn't take a dictionary, it takes a list of two item lists like so: f([ ["test", "testing"], ["wondered", "wonder"] ]) \$\endgroup\$
    – BookOwl
    Commented Nov 21, 2016 at 22:13
  • 1
    \$\begingroup\$ But that would add a byte. \$\endgroup\$
    – BookOwl
    Commented Nov 22, 2016 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.