No commit activity in last 3 years
No release in over 3 years
Determines the surplus of characters that satisfies a self-enumerating pangram.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0

Runtime

 Project Readme

Pangrammic Surplus

Determines the surplus of characters that satisfies a self-enumerating pangram.

Concept

When searching for self-enumerating pangrams, you'll often start with some boilerplate text and attempt to satisfy it with a list of numbers, for example:

This pangram lists one a, two b's, three c's ..... and one z.

In this case, the boilerplate is This pangram lists and

Pangrammic Surplus turns things the other way around. We give it a list of numbers and it tells us what characters are left to build boilerplate text from.

For example:

  require 'pangrammic_surplus'

  surplus = PangrammicSurplus.for(
    'a' => 4,  'b' => 1,  'c' => 1, 'd' => 2, 'e' => 29, 'f' => 8,  'g' => 3,
    'h' => 5,  'i' => 11, 'j' => 1, 'k' => 1, 'l' => 3,  'm' => 2,  'n' => 22,
    'o' => 15, 'p' => 2,  'q' => 1, 'r' => 7, 's' => 26, 't' => 19, 'u' => 4,
    'v' => 5,  'w' => 9,  'x' => 2, 'y' => 4, 'z' => 1
  )

  puts surplus.inspect
  # 'a' => 3, 'b' => 0, 'c' => 0, 'd' => 1, 'e' => 0, 'f' => 0, 'g' => 1,
  # 'h' => 1, 'i' => 2, 'j' => 0, 'k' => 0, 'l' => 1, 'm' => 1, 'n' => 2,
  # 'o' => 0, 'p' => 1, 'q' => 0, 'r' => 1, 's' => 3, 't' => 2, 'u' => 0,
  # 'v' => 0, 'w' => 0, 'x' => 0, 'y' => 0, 'z' => 0

  non_zero_letters = surplus.reject { |letter, count| count.zero? }
  puts non_zero_letters.inspect
  # 'a' => 3, 'd' => 1, 'g' => 1, 'h' => 1, 'i' => 2, 'l' => 1, 'm' => 1,
  # 'n' => 2, 'p' => 1, 'r' => 1, 's' => 3, 't' => 2

If we can construct boilerplate from an anagram of these letters, we have a true self-enumerating pangram.

This pangram lists and is one possible anagram, in this case.

And therefore, the following is a true self-enumerating pangram:

"This pangram lists four a's, one b, one c, two d's, twenty-nine e's, eight f's, three g's, five h's, eleven i's, one j, one k, three l's, two m's, twenty-two n's, fifteen o's, two p's, one q, seven r's, twenty-six s's, nineteen t's, four u's, five v's, nine w's, two x's, four y's, and one z."

Satisfiability

Self-enumerating pangrams can only be constructed from surpluses of positive integers because we can't remove characters from the minimal sentence structures:

A pangram can not be created from one e, because two have been used for that term alone. The surplus would infact be -1 before you even consider other terms.

In cases where there are no satisfiable pangrams for a given input, PangrammicSurplus.for returns nil, unless you pass true in for its second argument:

PangrammicSurplus.for({ 'e' => 1 }, allow_negatives = true)
#=> { 'e' => -1 }

This may be useful if you're writing an algorithm that checks just how unsatisfiable the given attempt was.