100 doors: Difference between revisions
m (→unoptimized: foreach is better name.) |
|||
Line 227: | Line 227: | ||
===unoptimized=== |
===unoptimized=== |
||
my @doors; |
my @doors; |
||
foreach my $pass (1 .. 100) { |
|||
foreach (1 .. 100) { |
|||
if (0 == $_ % $pass) { |
if (0 == $_ % $pass) { |
||
if (1 == $doors[$_]) { |
if (1 == $doors[$_]) { |
||
Line 239: | Line 239: | ||
}; |
}; |
||
print "$_\t$doors[$_]\n" |
print "$_\t$doors[$_]\n" foreach 1 .. 100; |
||
===optimized=== |
===optimized=== |
Revision as of 18:34, 13 February 2008
Problem: You have 100 doors in a row that are all initially closed. You make 100 passes by the doors, starting with the first door every time. The first time through, you visit every door and toggle the door (if the door is closed, you open it; if it is open, you close it). The second 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? [1]
Alternate: As noted in this page's discussion page, the only doors that remain open are whose numbers are perfect squares of integers. Opening only those doors is an optimization that may also be expressed.
Ada
unoptimized
with Ada.Text_Io; use Ada.Text_Io; procedure Doors is type Door_State is (Closed, Open); type Door_List is array(Positive range 1..100) of Door_State; The_Doors : Door_List := (others => Closed); begin for I in 1..100 loop for J in The_Doors'range loop if J mod I = 0 then if The_Doors(J) = Closed then The_Doors(J) := Open; else The_Doors(J) := Closed; end if; end if; end loop; end loop; for I in The_Doors'range loop Put_Line(Integer'Image(I) & " is " & Door_State'Image(The_Doors(I))); end loop; end Doors;
optimized
with Ada.Text_Io; use Ada.Text_Io; with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions; procedure Doors_Optimized is Num : Float; begin for I in 1..100 loop Num := Sqrt(Float(I)); Put(Integer'Image(I) & " is "); if Float'Floor(Num) = Num then Put_Line("Opened"); else Put_Line("Closed"); end if; end loop; end Doors_Optimized;
ALGOL 68
unoptimized
# declare some constants # INT limit = 100; PROC doors = VOID: ( MODE DOORSTATE = BOOL; BOOL closed = FALSE; BOOL open = NOT closed; MODE DOORLIST = [limit]DOORSTATE; DOORLIST the doors; FOR i FROM LWB the doors TO UPB the doors DO the doors[i]:=closed OD; FOR i FROM LWB the doors TO UPB the doors DO FOR j FROM LWB the doors TO UPB the doors DO IF j MOD i = 0 THEN the doors[j] := NOT the doors[j] FI OD OD; FOR i FROM LWB the doors TO UPB the doors DO printf(($g" is "gl$,i,(the doors[i]|"opened"|"closed"))) OD ); doors;
optimized
PROC doors optimised = ( INT limit )VOID: FOR i TO limit DO REAL num := sqrt(i); printf(($g" is "gl$,i,(ENTIER num = num |"opened"|"closed") )) OD ; doors optimised(limit)
D
module l00door ; import std.stdio ; alias char[] DOOR ; // or alias bool[] DOOR const char OPEN = 'O' ; // then OPEN = true const char CLOSE = 'x' ; // CLOSE = false
unoptimized
DOOR flip_u(inout DOOR d) { d[] = CLOSE ; for(int i= 0 ; i < d.length ; i++) for(int j = i ; j < d.length ; j += i + 1) if (d[j] == OPEN) d[j] = CLOSE ; else d[j] = OPEN ; return d ; }
optimized
DOOR flip_o(inout DOOR d) { d[] = CLOSE ; for(int i= 1 ; i*i <= d.length ; i++) d[i*i-1] = OPEN ; return d ; }
test program:
void main() { DOOR d ; d.length = 100 ; writefln(d.flip_u()) ; writefln(d.flip_o()) ; }
Forth
: doors ( n -- ) here over erase \ open all doors dup 0 do here over + here i + do i c@ 1 xor i c! \ toggle j 1+ +loop loop ." Closed doors: " ( n ) 0 do here i + c@ if i 1+ . then loop cr ; 100 doors
Haskell
unoptimized
data Door = Open | Closed deriving Show toggle f [] = [] toggle f (Open:xs) = Closed : f xs toggle f (Closed:xs) = Open : f xs pass k [] = [] pass k xs = ys ++ toggle (pass k) zs where (ys,zs) = splitAt k xs run n = snd $ (!! n) $ iterate (\(k,xs) -> (k+1, pass k xs)) $ (0, replicate n Closed)
optimized
(without using square roots)
gate :: Eq a => [a] -> [a] -> [Door] gate (x:xs) (y:ys) | x == y = Open : gate xs ys gate (x:xs) ys = Closed : gate xs ys gate [] _ = [] run n = gate [1..n] [k*k | k <- [1..]]
J
unoptimized
~:/ (100 $ - {. 1:)"0 >:i.100 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ...
optimized
(>:i.100) e. *: i.11 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ... 1 (<:*:i.10)} 100$0 NB. alternative 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ...
Java
unoptimized
public class Doors { public static void main(String[] args) { boolean[] doors = new boolean[100]; for(int pass = 0; pass < 100; pass++){ for(int door = pass; door < 100; door += pass + 1){ doors[door] = !doors[door]; } } for(int i = 0; i < 100; i++){ System.out.println("Door #" + (i + 1) + " is " + (doors[i] ? "open." : "closed.")); } } }
optimized
public class Doors { public static void main(String[] args) { boolean[] doors = new boolean[100]; for(int pass = 0; pass < 10; pass++){ doors[(pass + 1) * (pass + 1) - 1] = true; } for(int i = 0; i < 100; i++){ System.out.println("Door #" + (i + 1) + " is " + (doors[i] ? "open." : "closed.")); } } }
MAXScript
unoptimized
doorsOpen = for i in 1 to 100 collect false for pass in 1 to 100 do ( for door in pass to 100 by pass do ( doorsOpen[door] = not doorsOpen[door] ) ) for i in 1 to doorsOpen.count do ( format ("Door % is open?: %\n") i doorsOpen[i] )
optimized
for i in 1 to 100 do ( root = pow i 0.5 format ("Door % is open?: %\n") i (root == (root as integer)) )
Perl
unoptimized
my @doors; foreach my $pass (1 .. 100) { foreach (1 .. 100) { if (0 == $_ % $pass) { if (1 == $doors[$_]) { $doors[$_] = 0; } else { $doors[$_] = 1; }; }; }; }; print "$_\t$doors[$_]\n" foreach 1 .. 100;
optimized
while( ++$i <= 100 ) { $root = sqrt($i); if ( int( $root ) == $root ) { print "Door $i is open\n"; } else { print "Door $i is closed\n"; } }
Pop11
unoptimized
lvars i; lvars doors = {% for i from 1 to 100 do false endfor %}; for i from 1 to 100 do for j from i by i to 100 do not(doors(j)) -> doors(j); endfor; endfor; ;;; Print state for i from 1 to 100 do printf('Door ' >< i >< ' is ' >< if doors(i) then 'open' else 'closed' endif, '%s\n'); endfor;
optimized
lvars i, ri, rri, s; for i from 1 to 100 do sqrt(i) -> ri; round(ri) -> rri; if rri = ri then 'open' else 'closed' endif -> s; printf('Door ' >< i >< ' is ' >< s, '%s\n'); endfor;
Python
Note: both versions require Python 2.5 for the ternary syntax.
unoptimized
close = 0 open = 1 doors = [close] * 100 for i in range(100): for j in range(i, 100, i+1): doors[j] = open if doors[j] is close else close print "Door %d:" % (i+1), 'open' if doors[i] else 'close' for k, door in enumerate(doors): print "Door %d:" % (k+1), 'open' if door else 'close'
optimized
A version that only visits each door once:
for i in xrange(1, 101): root = i ** 0.5 print "Door %d:" % i, 'open' if root == int(root) else 'close'
Ruby
unoptimized
n = 100 Open = "open" Closed = "closed" def Open.f Closed end def Closed.f Open end doors = [Closed] * (n+1) for mul in 1..n for x in 1..n doors[mul*x] = (doors[mul*x] || break).f end end doors.each_with_index { |b, i| puts "Door #{i} is #{b}" if i>0 }
optimized
n = 100 doors = ["closed"] * (n+1) for x in 1..n doors[x**2] = (doors[x**2] || break) && "open" end doors.each_with_index { |b, i| puts "Door #{i} is #{b}" if i>0 }
Scheme
unoptimized
(define *max-doors* 100) (define (show-doors doors) (let door ((i 0) (l (vector-length doors))) (cond ((= i l) (newline)) (else (printf "~nDoor ~a is ~a" (+ i 1) (if (vector-ref doors i) "open" "closed")) (door (+ i 1) l))))) (define (flip-doors doors) (define (flip-all i) (cond ((> i *max-doors*) doors) (else (let flip ((idx (- i 1))) (cond ((>= idx *max-doors*) (flip-all (+ i 1))) (else (vector-set! doors idx (not (vector-ref doors idx))) (flip (+ idx i)))))))) (flip-all 1)) (show-doors (flip-doors (make-vector *max-doors* #f)))
optimized
(define (optimised-flip-doors doors) (define (flip-all i) (cond ((> i (floor (sqrt *max-doors*))) doors) (else (vector-set! doors (- (* i i) 1) #t) (flip-all (+ i 1))))) (flip-all 1)) (show-doors (optimised-flip-doors (make-vector *max-doors* #f)))
Visual Basic .NET
Platform: .NET
Language Version: 9.0+
unoptimized
Module Module1 Sub Main() Dim doors(100) As Boolean 'Door 1 is at index 0 For pass = 1 To 100 For door = pass - 1 To 99 Step pass doors(door) = Not doors(door) Next Next For door = 0 To 99 Console.WriteLine("Door # " & (door + 1) & " is " & If(doors(door), "Open", "Closed")) Next Console.ReadLine() End Sub End Module
optimized
Module Module1 Sub Main() Dim doors(100) As Boolean 'Door 1 is at index 0 For i = 1 To 10 doors(i ^ 2 - 1) = True Next For door = 0 To 99 Console.WriteLine("Door # " & (door + 1) & " is " & If(doors(door), "Open", "Closed")) Next Console.ReadLine() End Sub End Module