Module: Oulipo::StringExtensions

Included in:
EnhancedString, String
Defined in:
lib/oulipo/string_extensions.rb

Constant Summary collapse

ALPHABET =
'a'..'z'
VOWELS =
%w{ a e i o u }
ASCENDERS_AND_DESCENDERS =
%w{ b d f g h j k l p q t y }

Instance Method Summary collapse

Instance Method Details

#absent_lettersObject

Returns an array of letters that are absent



69
70
71
72
# File 'lib/oulipo/string_extensions.rb', line 69

def absent_letters
  remaining = ALPHABET.to_a - present_letters
  remaining.empty? ? nil : remaining
end

#alliteration?(options = {}) ⇒ Boolean

Whether the string uses alliteration or not. Accepts a :threshold option for determining whether the string uses sufficient alliteration (see #aliterativity)



10
11
12
13
# File 'lib/oulipo/string_extensions.rb', line 10

def alliteration?(options = {})
  threshold = options.delete(:threshold) || 1
  self.alliterativity >= threshold
end

#alliterativityObject

A score between 0 and 1 representing the level of alliteration



16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/oulipo/string_extensions.rb', line 16

def alliterativity
  words = self.downcase.gsub(/[^a-z\s]/, '').split
  leading_letters = words.map(&:chr)
  
  # { 'a' => 3, 'b' => 1, ... }
  leading_letter_counts = leading_letters.inject({}) do |result, letter|
    result[letter] ||= 0
    result[letter] += 1
    result
  end
  
  most_used_count = leading_letter_counts.max_by { |kv| kv.last }.pop
  most_used_count.to_f / words.length
end

#chaterism?Boolean

Returns true if the string is a sequence of words in each of which is one letter larger than the previous, or each word in the sequence is one letter less than the previous



57
58
59
60
61
62
63
64
65
66
# File 'lib/oulipo/string_extensions.rb', line 57

def chaterism?
  words = self.gsub(/[^a-z\s]/i, '').split

  # Find the direction we're traveling
  flen, llen = words.first.length, words.last.length
  direction = flen > llen ? :downto : :upto
  
  # Compare the pattern of word lengths against a range-turned-array of expected word lengths
  words.map(&:length) == flen.send(direction, llen).to_a
end

#lipogram?Boolean

Returns true if not all of the letters of the alphabet are used



84
85
86
# File 'lib/oulipo/string_extensions.rb', line 84

def lipogram?
  !self.pangram?
end

#n_plus(places, word_list) ⇒ Object

Replace the words in the word list with the word n places after it



38
39
40
41
42
# File 'lib/oulipo/string_extensions.rb', line 38

def n_plus(places, word_list)
  analysis = Analysis.new(self, :nouns => word_list)
  substitutor = Substitutor.new(analysis)
  substitutor.replace(:nouns).increment(places)
end

#palindrome?Boolean

The same letters backwards as forwards



32
33
34
35
# File 'lib/oulipo/string_extensions.rb', line 32

def palindrome?
  letter_sequence = self.downcase.gsub(/[^a-z]/, '')
  letter_sequence.reverse == letter_sequence
end

#pangram?Boolean

Returns true if all letters of the alphabet are used



79
80
81
# File 'lib/oulipo/string_extensions.rb', line 79

def pangram?
  self.absent_letters.nil?
end

#present_lettersObject



74
75
76
# File 'lib/oulipo/string_extensions.rb', line 74

def present_letters
  self.downcase.gsub(/[^a-z]/, '').split('').uniq.sort
end

#prisoner?Boolean

Returns true if no letters are ascenders (b, d, f, g, h, j, k, l) or descenders (p, q, t, y)



89
90
91
# File 'lib/oulipo/string_extensions.rb', line 89

def prisoner?
  (ASCENDERS_AND_DESCENDERS & present_letters).empty?
end

#snowball?Boolean

Returns true if each word is one letter larger than the previous



45
46
47
48
# File 'lib/oulipo/string_extensions.rb', line 45

def snowball?
  words = self.split
  self.chaterism? && words.first.length < words.last.length
end

#univocalism?Boolean

Returns true if only one vowel is used



51
52
53
# File 'lib/oulipo/string_extensions.rb', line 51

def univocalism?
  (VOWELS - present_letters).length == 4
end