Module: Poefy::ConditionalSatisfaction

Included in:
PoefyGen
Defined in:
lib/poefy/conditional_satisfaction.rb

Instance Method Summary collapse

Instance Method Details

#conditional_permutation(array, conditions, current_iter = 0, current_array = []) ⇒ Object

Return a permutation of ‘array’ where each element validates to the

same index in a 'conditions' array of procs that return Boolean.

Will not work on arrays that contain nil values.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/poefy/conditional_satisfaction.rb', line 133

def conditional_permutation array, conditions,
                            current_iter = 0,
                            current_array = []
  output = []

  # Get the current conditional.
  cond = conditions[current_iter]

  # Loop through and return the first element that validates.
  valid = false
  array.each do |elem|

    # Test the condition. If we've run out of elements
    #   in the condition array, then allow any value.
    valid = cond ? cond.call(current_array, elem) : true
    if valid

      # Remove this element from the array, and recurse.
      remain = array.dup
      delete_first(remain, elem)

      # If the remaining array is empty, no need to recurse.
      new_val = nil
      if !remain.empty?
        new_val = conditional_permutation(remain, conditions,
                                          current_iter + 1,
                                          current_array + [elem])
      end

      # If we cannot use this value, because it breaks future conditions.
      if !remain.empty? && new_val.empty?
        valid = false
      else
        output << elem << new_val
      end
    end

    break if valid
  end

  output.flatten.compact
end

#conditional_selection(array, conditions, current_iter = 0, current_array = []) ⇒ Object

Return values from ‘array’ where each element validates to the same

index in a 'conditions' array of procs that return Boolean.

Return an array of conditions.length



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/poefy/conditional_satisfaction.rb', line 179

def conditional_selection array, conditions,
                          current_iter = 0,
                          current_array = []
  output = []

  # Get the current conditional.
  cond = conditions[current_iter]

  # Return nil if we have reached the end of the conditionals.
  return nil if cond.nil?

  # Loop through and return the first element that validates.
  valid = false
  array.each do |elem|

    # Test the condition. If we've run out of elements
    #   in the condition array, then allow any value.
    valid = cond.call(current_array, elem)
    if valid

      # Remove this element from the array, and recurse.
      remain = array.dup
      delete_first(remain, elem)

      # If the remaining array is empty, no need to recurse.
      new_val = conditional_selection(remain, conditions,
                                      current_iter + 1,
                                      current_array + [elem])

      # If we cannot use this value, because it breaks future conditions.
      if new_val and new_val.empty?
        valid = false
      else
        output << elem << new_val
      end
    end

    break if valid
  end

  output.flatten.compact
end

#conditions_by_line(tokenised_rhyme, poetic_form) ⇒ Object

Input a rhyme array and a poetic_form hash. Create a line by line array of conditions. This will be used to analyse the validity of corpus lines.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/poefy/conditional_satisfaction.rb', line 87

def  tokenised_rhyme, poetic_form
  output = []
  tokenised_rhyme.each.with_index do |rhyme, index|
    line_hash = {
      line: index + 1,
      rhyme: rhyme[:token],
      rhyme_letter: rhyme[:rhyme_letter]
    }
    if rhyme[:refrain] and rhyme[:refrain] != ' '
      line_hash[:refrain] = rhyme[:refrain]
    end
    line_hash[:exact] = rhyme[:exact] if rhyme[:exact]
    poetic_form.keys.each do |k|
      if poetic_form[k].is_a? Hash
        line_hash[k] = poetic_form[k][index + 1]
      end
    end
    output << line_hash
  end
  output
end

#delete_first(array, value) ⇒ Object

Delete the first matching value in an array.



60
61
62
# File 'lib/poefy/conditional_satisfaction.rb', line 60

def delete_first array, value
  array.delete_at(array.index(value) || array.length)
end

#diff_end(arr, elem) ⇒ Object

Make sure each line ends with a different word. This is intented to be used in ‘conditions’ procs.



66
67
68
# File 'lib/poefy/conditional_satisfaction.rb', line 66

def diff_end arr, elem
  !arr.map{ |i| i['final_word'] }.include?(elem['final_word'])
end

#unique_rhymes(tokenised_rhyme) ⇒ Object

Group by element, with count as value. Ignore spaces. e.g. “b”=>6, “A2”=>4, “a”=>5

=>  {"b"=>6, "a"=>7}


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/poefy/conditional_satisfaction.rb', line 112

def unique_rhymes tokenised_rhyme

  # Group by element, with count as value. Ignore spaces.
  # e.g. {"A1"=>4, "b"=>6, "A2"=>4, "a"=>5}
  tokens = tokenised_rhyme.reject { |i| i == ' ' }
  grouped = tokens.each_with_object(Hash.new(0)) { |k,h| h[k] += 1 }

  # For each uppercase token, add one to the corresponding lowercase.
  uppers = grouped.keys.select{ |i| /[[:upper:]]/.match(i) }
  uppers.each { |i| grouped[i[0].downcase] += 1 }

  # Delete from the grouped hash if uppercase.
  grouped.delete_if { |k,v| /[[:upper:]]/.match(k) }
  grouped
end

#validate_line(line, poetic_form) ⇒ Object

See if a line matches to a particular ‘poetic_form’



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/poefy/conditional_satisfaction.rb', line 71

def validate_line line, poetic_form
  valid = true
  if poetic_form[:syllable] and poetic_form[:syllable] != 0
    valid = valid && [*poetic_form[:syllable]].include?(line['syllables'])
  end
  if poetic_form[:regex]
    [*poetic_form[:regex]].each do |i|
      valid = valid && !!(line['line'].match(i))
    end
  end
  valid
end