patternrubyMinor
Look-and-say sequence
Viewed 0 times
andsaylooksequence
Problem
Here is my code in Ruby that shows the look-and-say sequence. It shows correct result, but my teacher said, that I could actually make it better. Can you tell me what the flaws are there in my code?
In the input I tell how many sequence elements I want to see.
For example I type
and get:
In the input I tell how many sequence elements I want to see.
For example I type
5and get:
1
11
21
1211
111221class NumberSequence
def self.start
puts 'Enter the number of elements in sequence'
count = gets.to_i - 1
number = "1"
times = 1
puts number
count.times do
result = ""
c = number[0]
number = number[1..-1]+" "
number.chars.each do |char|
if(c!=char)
result+= times.to_s+c
times = 1
c = char
else
times+=1
end
end
number = result
puts(result)
end
end
end
NumberSequence.startSolution
Interface design
You've lumped all of the functionality into one function. At the least, you should have a function that is responsible for sequence-generating, and another for the prompting and printing.
To me, this problem cries out to be treated as a enumerator. With an enumerator, you would automatically benefit from all of the members of the
Since this is an infinite sequence, one tricky bit is to ensure that you define a lazy enumerator so that it doesn't try to generate the entire infinite sequence.
Implementation
The implementation would be a lot simpler if you took advantage of
Suggested solution
… and a bonus variant
You've lumped all of the functionality into one function. At the least, you should have a function that is responsible for sequence-generating, and another for the prompting and printing.
To me, this problem cries out to be treated as a enumerator. With an enumerator, you would automatically benefit from all of the members of the
Enumerable mixin, especially #take, which takes the first n elements.Since this is an infinite sequence, one tricky bit is to ensure that you define a lazy enumerator so that it doesn't try to generate the entire infinite sequence.
Implementation
The implementation would be a lot simpler if you took advantage of
Enumerable#chunk.Suggested solution
module LookAndSaySequence
# An enumerator that generates the sequence "1", "11", "21", "1211", ...
# (or with some other initial string of digits)
def self.strings(init='1')
Enumerator.new do |y|
s = init
loop do
y << s
s = s.chars
.chunk { |digit| digit }
.map { |digit, list| list.length.to_s + digit }
.join
end
end.lazy
end
end
print 'Enter the number of elements in sequence: '
LookAndSaySequence.strings.take(gets.to_i).each { |s| puts s }… and a bonus variant
LookAndSaySequence.numbers that produces Fixnums instead of Strings:module LookAndSaySequence
# An enumerator that generates the sequence 1, 11, 21, 1211, ...
# (or with some other initial number)
def self.numbers(init=1)
strings(init.to_s).map { |s| s.to_i }
end
endCode Snippets
module LookAndSaySequence
# An enumerator that generates the sequence "1", "11", "21", "1211", ...
# (or with some other initial string of digits)
def self.strings(init='1')
Enumerator.new do |y|
s = init
loop do
y << s
s = s.chars
.chunk { |digit| digit }
.map { |digit, list| list.length.to_s + digit }
.join
end
end.lazy
end
end
print 'Enter the number of elements in sequence: '
LookAndSaySequence.strings.take(gets.to_i).each { |s| puts s }module LookAndSaySequence
# An enumerator that generates the sequence 1, 11, 21, 1211, ...
# (or with some other initial number)
def self.numbers(init=1)
strings(init.to_s).map { |s| s.to_i }
end
endContext
StackExchange Code Review Q#110552, answer score: 4
Revisions (0)
No revisions yet.