Skip to content

Instantly share code, notes, and snippets.

@FiveYellowMice
Created November 27, 2016 15:28
Show Gist options
  • Save FiveYellowMice/36860b44fbd14b63e9104dc29307e43e to your computer and use it in GitHub Desktop.
Save FiveYellowMice/36860b44fbd14b63e9104dc29307e43e to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# frozen_string_literal: true
class HoroSpeak
attr_accessor :debug_mode
def initialize(library_filename, options = {})
@sentences = File.readlines(library_filename).reduce([]) do |memo, line|
stripped = line.strip
if stripped.empty?
memo
else
memo << stripped
end
end
@debug_mode = options[:debug_mode]
end
def get_answer(request, avoided_index = nil, last_segment = '', recursion_level = 0)
selected_sentence_index = nil
([5, 6, 7, 8].sample(2) + [2, 3, 4].shuffle + [1, 0]).find do |last_char_count|
[0, 1, 2].find do |skip_char_count|
last_chars = request[
[request.length - last_char_count - skip_char_count, 0].max...
[request.length - skip_char_count, 0].max
]
if last_chars.length == last_char_count
random_indices.find do |sentence_index|
sentence = @sentences[sentence_index]
if sentence_index != avoided_index && (sentence[-10..-1] || sentence).include?(last_chars)
selected_sentence_index = sentence_index
end
end
end
end
end
return unless selected_sentence_index
answer = last_segment
answer_slice_index = 0
times_looped = 0
while answer.length < 32 && times_looped < 200
debug_puts { "DEBUG: Start while loop for #{times_looped} time, answer: #{answer}" }
selected_sentence = @sentences[selected_sentence_index]
last_chars = ''
new_sentence_found =
([3, 4, 5].shuffle + [2]).find do |last_char_count|
last_chars = selected_sentence[answer_slice_index, last_char_count]
next if last_chars.empty?
if
answer.empty? ||
last_chars.length == last_char_count ||
selected_sentence[0...answer_slice_index].end_with?(answer + last_chars)
then
random_indices.find do |sentence_index|
if
sentence_index != selected_sentence_index ||
selected_sentence.length < answer_slice_index + last_chars.length + 3
then
sentence = @sentences[sentence_index]
sentence_last_chars_index = sentence.index(last_chars)
if sentence_last_chars_index
answer += last_chars
selected_sentence_index = sentence_index
answer_slice_index = sentence_last_chars_index + last_chars.length
yield last_chars
true
end
end
end
end
end
if !new_sentence_found
if answer.empty?
selected_sentence_index = (selected_sentence_index + 1) % @sentences.length
answer_slice_index = 0
elsif
recursion_level < 20 && (
@sentences.include?(answer + last_chars) ||
selected_sentence[0...answer_slice_index].end_with?(answer)
)
then
answer += last_chars
yield last_chars
if ['。', ',', '!', '?', '…', '—', ':', ';', ',', '.', '?', '!', '-', ':', ';'].include?(answer[-1])
last_segment = answer + ' '
yield ' '
else
last_segment = answer
end
debug_puts { "DEBUG: Enter recursion level #{recursion_level + 1}, answer: #{answer}" }
get_answer(answer, selected_sentence_index, last_segment, recursion_level + 1) do |segment|
answer += segment
yield segment
end
debug_puts { "DEBUG: Exit recursion level #{recursion_level + 1}, answer: #{answer}" }
else
yield last_chars
return
end
end
times_looped += 1
end
end
private
def random_indices(max_number = 200)
sentence_indices = (0...@sentences.length).to_a
if max_number == 0
sentence_indices.shuffle
else
sentence_indices.sample(max_number)
end
end
def debug_puts
@debug_mode && puts(yield)
end
end
generator = HoroSpeak.new(ARGV[0] || 'sayings.txt')
if ENV['HOROSPEAK_DEBUG']
generator.debug_mode = true
end
last_request = []
loop do
print '> '
request = (STDIN.gets || break).chomp
if request.empty?
request = last_request.join
end
last_request = []
generator.get_answer(request) do |segment|
last_request << segment
end
puts last_request.join
end
puts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment