Successfully reported this slideshow.
Upcoming SlideShare
×

# 100 doors kata solution

1,576 views

Published on

• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

• Be the first to like this

### 100 doors kata solution

1. 1. My attempt to solve 100 Doors kataSteven MakThursday, 6 June, 13
2. 2. Change history2Do you have experience that you think your code is already the best solution, butafter a while you can think of ways improving it? This does happen to me withthis kata. That’s why I decided to add this slide showing history of the changes.I might not be updating the code here often, especially these changes didn’tchange the overall thinking or analysis of the problem. You can refer to thesource here: https://github.com/tcmak/kata-100-doors• 2013-06-04: Initial solution, rather procedural• 2013-06-05: Apply recursion for shouldOpenInRound methodThursday, 6 June, 13
3. 3. 100 Doors Kata3Reference: http://rosettacode.org/wiki/100_doorsTo quote how they describe the problem:“Problem: You have 100 doors in a row that are all initially closed. You make100 passes by the doors. The ﬁrst time through, you visit every door and togglethe door (if the door is closed, you open it; if it is open, you close it). Thesecond time you only visit every 2nd door (door #2, #4, #6, ...). The third time,every 3rd door (door #3, #6, #9, ...), etc, until you only visit the 100th door.Question: What state are the doors in after the last pass? Which are open,which are closed?”(Spoiler warning: you might not want to continue if you haven’t done this kata before)Thursday, 6 June, 13
4. 4. First test -all doors are close at the beginning4 it("All doors closed at the beginning", function() local doors = doors(0) for i,door in ipairs(doors) do assert.is_false(door) end end)Thursday, 6 June, 13
5. 5. Simple implementation5local function doors(round) local doors = {} for i = 1, NUM_DOORS do doors[i] = false end return doorsendNUM_DOORS = 100(my apology for using global variables for now)Thursday, 6 June, 13
6. 6. Second test -all doors opened after the ﬁrst pass6 it("All doors open after the first round", function() local doors = doors(1) for i,door in ipairs(doors) do assert.is_true(door) end end)Thursday, 6 June, 13
7. 7. Another Simple implementation andextract doors initialization to its own function7local function doors(round) local doors = initializeDoors() if round == 0 then return doors end for i = 1, NUM_DOORS do doors[i] = true end return doorsendThursday, 6 June, 13
8. 8. Third test -only alternative doors opened8 it("Second round, alternative doors are open", function() local doors = doors(2) for i= 1,NUM_DOORS, 2 do assert.is_true(doors[i]) end for i= 2,NUM_DOORS, 2 do assert.is_false(doors[i]) end end)Thursday, 6 June, 13
9. 9. Let’s fake it for now as if I know the solution9local function doors(round) local doors = initializeDoors() if round == 0 then return doors end for i = 1, NUM_DOORS do if (i+1) % round == 0 then doors[i] = true end end return doorsendYou are right, at this moment I still haveno clue how the complete solution is like,or any pattern related to the problemThursday, 6 June, 13
10. 10. Fourth test -what is it???10 it("All doors closed at the beginning", function() ... ... end) it("All doors open after the first round", function() ... ... end) it("Second round, alternative doors are open", function() ... ... end)It does not seem to have any easy way todescribe the pattern in the next testThursday, 6 June, 13
11. 11. Fourth test -get a piece of paper and do some math11Doors Pass 1 Pass 2 Pass 31 Open Open Open2 Open Close Close3 Open Open Close4 Open Close Close5 Open Open Open6 Open Close Open7 Open Open Open8 Open Close Close9 Open Open Close10 Open Close CloseThursday, 6 June, 13
12. 12. Fourth test -think deeper12Doors Pass 1 Pass 2 Pass 3 ﬂips#1 Open Open Open 12 Open Close Close 23 Open Open Close 24 Open Close Close 25 Open Open Open 16 Open Close Open 37 Open Open Open 18 Open Close Close 29 Open Open Close 210 Open Close Close 2Do you see the pattern:Whether a door is closed or openeddepends on the number of numbers,limited by the number of passes, whichcan divide this door number.For example:9 is divisible by 1 and 36 is divisible by 1, 2, and 3If this number of factors is odd, then it willbe opened, otherwise it is closedThursday, 6 June, 13
13. 13. Put the original kata aside for nowand do this little kata13For any integer N, how many integers, which are less than or equal toanother given integer R, that can divide N(for 100-door kata, we are only concerned if it is odd or even)For example:N R result Odd?1 1 1 TRUE2 2 2 FALSE3 3 2 FALSE4 2 2 FALSE4 4 3 TRUEThursday, 6 June, 13
14. 14. I will leave the process of solvingthis kata for your own pleasure14local function shouldOpenInRound(number, round) local shouldOpen = false for factor=1,round do if number % factor == 0 then shouldOpen = not shouldOpen end end return shouldOpenendThursday, 6 June, 13
15. 15. Fourth test -Let’s continue15 it("Third round, [1 0 0 0 1 1]", function() local originalNumOfDoors = NUM_DOORS NUM_DOORS = 6 local doors = doors(3) assert.is_true(doors[1]) assert.is_false(doors[2]) assert.is_false(doors[3]) assert.is_false(doors[4]) assert.is_true(doors[5]) assert.is_true(doors[6]) NUM_DOORS = originalNumOfDoors end)Thursday, 6 June, 13
16. 16. Now it’s an easy piece of cake16local function doors(round) local doors = initializeDoors() if round == 0 then return doors end for i = 1, NUM_DOORS do if shouldOpenInRound(i, round) then doors[i] = true end end return doorsendThursday, 6 June, 13
17. 17. Refactor and remove redundant code17NUM_DOORS = 100local function shouldOpenInRound(number, round) local shouldOpen = false for factor=1,round do if number % factor == 0 then shouldOpen = not shouldOpen end end return shouldOpenendlocal function doors(round) local doors = {} for i = 1, NUM_DOORS do doors[i] = shouldOpenInRound(i, round) end return doorsendThursday, 6 June, 13
18. 18. Fifth test -conﬁrming this is right18 it("100th round, 1,4,9,16...100", function() local doors = doors(100) for i=1,NUM_DOORS do if math.sqrt(i) == math.ceil(math.sqrt(i)) then assert.is_true(doors[i]) else assert.is_false(doors[i]) end end end)Yay! things pass as expected. Smile!Thursday, 6 June, 13
19. 19. In retrospect...• What if I follow TPP strictly?• Is this the most optimal solution?• Shall this code be more OO or functional?• Can these functions be shorter/cleaner?Updates can be found at: https://github.com/tcmak/kata-100-doorsThank you for spending time on this.More feedback can be sent to:19Steven Mak 麥天志steven@odd-e.comhttp://www.odd-e.comhttps://twitter.com/stevenmakhttp://weibo.com/oddeOdd-e Hong Kong Ltd.Steven Mak 麥天志Agile CoachHong KongEmail: steven@odd-e.comWeb: www.odd-e.comTwitter: stevenmakThursday, 6 June, 13