Forum: Ruby alarm.rb (#73)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
James G. (Guest)
on 2006-03-29 19:09
(Received via mailing list)
The three rules of Ruby Q.:

1.  Please do not post any solutions or spoiler discussion for this quiz
until
48 hours have passed from the time on this message.

2.  Support Ruby Q. by submitting ideas as often as you can:

http://www.rubyquiz.com/

3.  Enjoy!

Suggestion:  A [QUIZ] in the subject of emails about the problem helps
everyone
on Ruby T. follow the discussion.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#!/usr/bin/env ruby -w

#
# Stephen W. <removed_email_address@domain.invalid>
#

class AlarmKeypad

	# init a keypad, with length of security code, and the code's stop
digits
	def initialize(code_length = 4, stop_digits = [1,2,3])
		# remember the length of the security code
		@code_length = code_length

		# and which digits cause a code to be checked
		@stop_digits = stop_digits

		# and reset our data structures to 0
		clear
	end


	# reset keypad to initial state
	def clear
		# an array of each code and how many times it's been entered
		@codes       = Array.new(10**@code_length,0)

		# last N+1 keypad button presses
		@key_history = []

		# total number of keypad button presses
		@key_presses = 0
	end


	# press a single digit
	def press(digit)
		# add digit to key history
		@key_history.shift while @key_history.size > @code_length
		@key_history << digit
		@key_presses += 1

		# see if we just tested a code
		if @stop_digits.include?(@key_history.last) and
		   @key_history.length > @code_length
			@codes[@key_history[0,@code_length].join.to_i] += 1
		end
	end

	# find out if every code had been tested
	def fully_tested?
		not @codes.include?(0)
	end

	# find out if an individual code has been tested
	# NOTE: an actual keypad obviously doesn't offer this functionality;
	#       but, it's useful and convenient (and might save duplication)
	def tested?(code)
		@codes[code] > 0
	end

	# output a summary
	def summarize
		tested          = @codes.select { |c| c > 0 }.size
		tested_multiple = @codes.select { |c| c > 1 }.size

		puts "Search space exhausted." if fully_tested?
		puts "Tested #{tested} of #{@codes.size} codes " +
		     "in #{@key_presses} keystrokes."
		puts "#{tested_multiple} codes were tested more than once."
	end
end

if $0 == __FILE__
	# a random button presser, 3 digit codes
	a = AlarmKeypad.new(3)
	a.press( rand(10) ) until a.fully_tested?
	a.summarize

	# sequential code entry, 4 digit codes
	a = AlarmKeypad.new(4)
	("0000".."9999").each do |c|
		next if a.tested?(c.to_i)
		c.split(//).each { |d| a.press(d.to_i) }
		a.press(rand(3)+1)
	end
	a.summarize

	# sequential code entry, 5 digit codes, only [1] as a stop digit
	a = AlarmKeypad.new(5,[1])
	("00000".."99999").each do |c|
		next if a.tested?(c.to_i)
		c.split(//).each { |d| a.press(d.to_i) }
		a.press(1)
	end
	a.summarize
end
James G. (Guest)
on 2006-03-29 19:09
(Received via mailing list)
Sorry about this message folks.  It was a comical naming error.  I
was testing one of the solutions and it triggered the quiz posting
software.  :D

James Edward G. II
This topic is locked and can not be replied to.