Reputation: 23
I am trying to solve a challenge where I have 100 empty boxes and every time you touch an empty box you are supposed to fill it and every time you touch a filled box you must empty it. The boxes all start out empty.
You are supposed to first touch every box, then every other box, then every 3rd box, then every 4th box until you are touching every 100th box.
I am trying to create a program that symbolizes this. I am doing so by creating a boxes hash and then doing a double while loop once I have the hash that I want to iterate as directed. However my output is:
{1=>"1", 2=>"1", 3=>"1", 4=>"1", 5=>"1", 6=>"1", 7=>"1", 8=>"1", 9=>"1", 10=>"1", 11=>"1", 12=>"1", 13=>"1", 14=>"1", 15
=>"1", 16=>"1", 17=>"1", 18=>"1", 19=>"1", 20=>"1", 21=>"1", 22=>"1", 23=>"1", 24=>"1", 25=>"1", 26=>"1", 27=>"1", 28=>"
1", 29=>"1", 30=>"1", 31=>"1", 32=>"1", 33=>"1", 34=>"1", 35=>"1", 36=>"1", 37=>"1", 38=>"1", 39=>"1", 40=>"1", 41=>"1",
42=>"1", 43=>"1", 44=>"1", 45=>"1", 46=>"1", 47=>"1", 48=>"1", 49=>"1", 50=>"1", 51=>"1", 52=>"1", 53=>"1", 54=>"1", 55
=>"1", 56=>"1", 57=>"1", 58=>"1", 59=>"1", 60=>"1", 61=>"1", 62=>"1", 63=>"1", 64=>"1", 65=>"1", 66=>"1", 67=>"1", 68=>"
1", 69=>"1", 70=>"1", 71=>"1", 72=>"1", 73=>"1", 74=>"1", 75=>"1", 76=>"1", 77=>"1", 78=>"1", 79=>"1", 80=>"1", 81=>"1",
82=>"1", 83=>"1", 84=>"1", 85=>"1", 86=>"1", 87=>"1", 88=>"1", 89=>"1", 90=>"1", 91=>"1", 92=>"1", 93=>"1", 94=>"1", 95
=>"1", 96=>"1", 97=>"1", 98=>"1", 99=>"1", 100=>"1"}
This doesn't seem right as some boxes should be full(e.i = 1) and some should be empty(e.i = 0) but my result shows them all full... What am I doing wrong?
Here is my code, thanks in advance:
number_setter = 1
boxes = {}
while number_setter <= 100 do
boxes[number_setter] = '0'
number_setter += 1
end
iteration_setter = 1
increaser = 1
while increaser <= 100 do
while iteration_setter <= 100 do
if boxes[iteration_setter] == '0'
boxes[iteration_setter] = '1'
elsif boxes[iteration_setter] == '1'
boxes[iteration_setter] = '0'
else
puts "something is not right on #{iteration_setter} hash key"
end
iteration_setter += increaser
end
increaser += 1
end
puts boxes
Upvotes: 0
Views: 47
Reputation: 110675
I assume you are not looking for a mathematical solution (whether box i
is empty or filled at the end can be expressed as a function of i
).
Ruby has a number of methods that can be helpful here. One is Array#cycle, which returns an enumerator:
state = [:empty, :filled]
touch = state.cycle
#=> #<Enumerator: [:empty, :filled]:cycle>
which allows us to write:
touch.next #=> :empty
touch.next #=> :filled
touch.next #=> :empty
rather than something clunky like
touch = (touch==:empty) ? :filled : :empty
We first want to create an array of boxes, the value of each being this enumerator:
nboxes = 20
boxes = Array.new(nboxes) { [:empty, :filled].cycle }
Another useful method is Range#step, allowing us to write:
npasses = 100
(1..npasses).each { |n| (0...nboxes).step(n).each { |i| boxes[i].next } }
We can then examine the state of each box:
boxes.map(&:next)
You may have noticed that the first time a box is touched, it's state is set to :empty
, which is incorrect. However, the last line above, which retrieves the final state applies .next
, which gets the "next" state, correcting the error at the beginning (since there are two states).
Putting this together:
def touch_boxes(nboxes, npasses=100)
boxes = Array.new(nboxes) { [:empty, :filled].cycle }
(1..npasses).each { |n| (0...nboxes).step(n).each { |i| boxes[i].next } }
boxes.map(&:next)
end
touch_boxes(20, npasses=1)
#=> [:filled, :filled, :filled, :filled, :filled,
# :filled, :filled, :filled, :filled, :filled,
# :filled, :filled, :filled, :filled, :filled,
# :filled, :filled, :filled, :filled, :filled]
touch_boxes(20, npasses=2)
#=> [:empty, :filled, :empty, :filled, :empty,
# :filled, :empty, :filled, :empty, :filled,
# :empty, :filled, :empty, :filled, :empty,
# :filled, :empty, :filled, :empty, :filled]
touch_boxes(20, npasses=3)
#=> [:filled, :filled, :empty, :empty, :empty,
# :filled, :filled, :filled, :empty, :empty,
# :empty, :filled, :filled, :filled, :empty,
# :empty, :empty, :filled, :filled, :filled]
touch_boxes(20, npasses=20)
#=> [:empty, :filled, :empty, :empty, :filled,
# :empty, :empty, :empty, :empty, :filled,
# :empty, :empty, :empty, :empty, :empty,
# :empty, :filled, :empty, :empty, :empty]
Upvotes: 0
Reputation: 146073
Well, for one thing, you never start iteration_setter
over again, so it just remains 101
forever...
Moving iteration_setter = 1
to the line right before while iteration_setter <= 100 do
should do the trick.
Upvotes: 1