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)

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


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)

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


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

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