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\$ – OldBunny2800 Nov 16 '16 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 Nov 16 '16 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\$ – ETHproductions Nov 16 '16 at 2:02
  • \$\begingroup\$ Yeah... just trying to simplify things a bit @Geobits! \$\endgroup\$ – OldBunny2800 Nov 16 '16 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 Nov 16 '16 at 2:05

Pyth, 28 bytes

Really want to condense the logic.


Try it online here.

| improve this answer | |
  • \$\begingroup\$ Congrats! Good answer! \$\endgroup\$ – OldBunny2800 Nov 16 '16 at 4:27
  • \$\begingroup\$ ["test - testing"] returns True \$\endgroup\$ – OldBunny2800 Nov 22 '16 at 0:03
  • 1
    \$\begingroup\$ @OldBunny2800 oh, that's cuz True is 1 in python \$\endgroup\$ – Maltysen Nov 22 '16 at 0:04
  • \$\begingroup\$ OK then. I can't break it, and that's a good thing! \$\endgroup\$ – OldBunny2800 Nov 22 '16 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
| improve this answer | |
  • \$\begingroup\$ Nice! Quick answer. \$\endgroup\$ – OldBunny2800 Nov 16 '16 at 2:35
  • \$\begingroup\$ c({"a":"aed","bed":"b"}) returns 0, it should return 2. \$\endgroup\$ – OldBunny2800 Nov 16 '16 at 2:38
  • \$\begingroup\$ Golfed code, Python 2 only. Still as buggy as your current code, though :) \$\endgroup\$ – Erik the Outgolfer Nov 17 '16 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\$ – ender_scythe Nov 17 '16 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
| improve this answer | |
  • \$\begingroup\$ What is the def f(d,n=0): part for? What is the input in n used for? \$\endgroup\$ – OldBunny2800 Nov 17 '16 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 Nov 21 '16 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\$ – OldBunny2800 Nov 21 '16 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 Nov 21 '16 at 22:13
  • 1
    \$\begingroup\$ But that would add a byte. \$\endgroup\$ – BookOwl Nov 22 '16 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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