100 doors

From Rosetta Code
100 doors is a programming puzzle. It lays out a problem which Rosetta Code users are encouraged to solve, using languages and techniques they know. Multiple approaches are not discouraged, so long as the puzzle guidelines are followed. For other Puzzles, see Category:Puzzles.

Problem: You have 100 doors in a row that are all initially closed. You make 100 passes by the doors. 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.

6502 Assembly

Works with: [6502asm.com] version 1.2

optimized (Largely inspired by the optimized C implementation) <lang 6502asm>

                       ;assume all memory is initially set to 0
         inc $1        ;start out with a delta of 1

openloop: inc $200,X ;open a door at X

         inc $1        ;add 2 to delta
         inc $1
         txa           ;add delta to X
         adc $1
         tax
         cpx #$65      ;check to see if we're at the 100th door
         bmi openloop  ;jump back to openloop if less than 100</lang>

8086 Assembly

See 100 doors/8086 Assembly

ActionScript

Works with: ActionScript version 3.0

unoptimized <lang actionscript>package {

   import flash.display.Sprite;                                              
   public class Doors extends Sprite {
       public function Doors() {
           // Initialize the array
           var doors:Array = new Array(100);
           for (var i:Number = 0; i < 100; i++) {
               doors[i] = false;
           // Do the work
           for (var pass:Number = 0; pass < 100; pass++) {
               for (var j:Number = pass; j < 100; j += (pass+1)) {
                   doors[j] = !doors[j];
               }
           }
           trace(doors);
       }
   }

}</lang>

Ada

unoptimized <lang ada>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;</lang>

optimized <lang ada>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;</lang>

Aikido

<lang aikido> var doors = new int [100]

foreach pass 100 {

   for (var door = pass ; door < 100 ; door += pass+1) {
       doors[door] = !doors[door]
   }

}

var d = 1 foreach door doors {

   println ("door " + d++ + " is " + (door ? "open" : "closed"))

}

</lang>

ALGOL 68

unoptimized <lang algol68># 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;</lang> optimized <lang algol68>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)</lang>

AmigaE

<lang amigae>PROC main()

 DEF t[100]: ARRAY,
     pass, door
 FOR door := 0 TO 99 DO t[door] := FALSE
 FOR pass := 0 TO 99
   door := pass
   WHILE door <= 99
     t[door] := Not(t[door])
     door := door + pass + 1
   ENDWHILE
 ENDFOR
 FOR door := 0 TO 99 DO WriteF('\d is \s\n', door+1,
                               IF t[door] THEN 'open' ELSE 'closed')

ENDPROC</lang>

Argile

<lang Argile>use std, array

close all doors for each pass from 1 to 100

 for (door = pass) (door <= 100) (door += pass)
   toggle door

let int pass, door.

.: close all doors :. {memset doors 0 size of doors} .:toggle <int door>:. {  !!(doors[door - 1]) }

let doors be an array of 100 bool

for each door from 1 to 100

 printf "#%.3d %s\n" door (doors[door - 1]) ? "[ ]", "[X]"</lang>

AutoHotkey

Standard Approach

<lang autohotkey>Loop, 100

 Door%A_Index% := "closed"

Loop, 100 {

 x := A_Index, y := A_Index
 While (x <= 100)
 {
   CurrentDoor := Door%x%
   If CurrentDoor contains closed
   {
     Door%x% := "open"
     x += y
   }
   else if CurrentDoor contains open
   {
     Door%x% := "closed"
     x += y
   }
 }

}

Loop, 100 {

  CurrentDoor := Door%A_Index%
  If CurrentDoor contains open
     Res .= "Door " A_Index " is open`n"

} MsgBox % Res</lang>

Alternative Approach

Making use of the identity:

<lang autohotkey>increment := 3, square := 1 Loop, 100

   If (A_Index = square) 
       outstring .= "`nDoor " A_Index " is open" 
       ,square += increment, increment += 2 

MsgBox,, Succesfull, % SubStr(outstring, 2)</lang>

Optimized

<lang autohotkey>While (Door := A_Index ** 2) <= 100

  Result .= "Door " Door " is open`n"

MsgBox, %Result%</lang>

AWK

unoptimized <lang awk>BEGIN {

 for(i=1; i <= 100; i++)
 {
   doors[i] = 0 # close the doors
 }
 for(i=1; i <= 100; i++)
 {
   for(j=i; j <= 100; j += i)
   {
     doors[j] = (doors[j]+1) % 2
   }
 }
 for(i=1; i <= 100; i++)
 {
   print i, doors[i] ? "open" : "close"
 }

}</lang> optimized <lang awk>BEGIN {

 for(i=1; i <= 100; i++) {
   doors[i] = 0 # close the doors
 }
 for(i=1; i <= 100; i++) {
   if ( int(sqrt(i)) == sqrt(i) ) {
     doors[i] = 1
   }
 }
 for(i=1; i <= 100; i++)
 {
   print i, doors[i] ? "open" : "close"
 }

}</lang>

Batch File

unoptimized <lang dos>@echo off setlocal enabledelayedexpansion for /l %%p in (1,1,100) do ( for /l %%d in (%%p,%%p,100) do ( if not defined door%%d ( set door%%d=closed ) else ( call :toggle door%%d ) ) )

for /l %%d in (1,1,100) do (

echo door%%d=!door%%d! ) goto :eof

toggle

if !%1! equ open ( set %1=closed ) else ( set %1=open ) goto :eof</lang>

BASIC

Works with: QuickBasic version 4.5

unoptimized <lang qbasic>DIM doors(0 TO 99) FOR pass = 0 TO 99 FOR door = pass TO 99 STEP pass + 1 PRINT doors(door) PRINT NOT doors(door) doors(door) = NOT doors(door) NEXT door NEXT pass FOR i = 0 TO 99 PRINT "Door #"; i + 1; " is "; IF NOT doors(i) THEN PRINT "closed" ELSE PRINT "open" END IF NEXT i</lang> optimized <lang qbasic>DIM doors(0 TO 99) FOR door = 0 TO 99 IF INT(SQR(door)) = SQR(door) THEN doors(door) = -1 NEXT door FOR i = 0 TO 99 PRINT "Door #"; i + 1; " is "; IF NOT doors(i) THEN PRINT "closed" ELSE PRINT "open" END IF NEXT i</lang>

Befunge

Works with: CCBI version 2.1

<lang befunge>108p0>:18p;;>:9g!18g9p08g]

  • `!0\|+relet|-1`*aap81::+]
+1<r]!g9;>$08g1+
08paa[
  • `#@_^._aa</lang>

C

unoptimized <lang c>#include <stdio.h>

int main() {

 char is_open[100] = { 0 };
 int pass, door;
 // do the 100 passes
 for (pass = 0; pass < 100; ++pass)
   for (door = pass; door < 100; door += pass+1)
     is_open[door] = !is_open[door];
 // output the result
 for (door = 0; door < 100; ++door)
   printf("door #%d is %s.\n", door+1, (is_open[door]? "open" : "closed"));
 return 0;

}</lang>

optimized This optimized version makes use of the fact that finally only the doors with square index are open, as well as the fact that .

<lang c>#include <stdio.h>

int main() {

 int square = 1, increment = 3, door;
 for (door = 1; door <= 100; ++door)
 {
   printf("door #%d", door);
   if (door == square)
   {
     printf(" is open.\n");
     square += increment;
     increment += 2;
   }
   else
     printf(" is closed.\n");
 }
 return 0;

}</lang>

The following ultra-short optimized version demonstrates the flexibility of C loops, but isn't really considered good C style:

<lang c>#include <stdio.h>

int main() {

 int door, square, increment;
 for (door = 1, square = 1, increment = 1; door <= 100; door++ == square && (square += increment += 2))
   printf("door #%d is %s.\n", door, (door == square? "open" : "closed"));
 return 0;

}</lang>

C++

Works with: GCC version 4.1.2 20061115 (prerelease) (SUSE Linux)

unoptimized <lang cpp>#include <iostream>

int main() {

 bool is_open[100] = { false };
 // do the 100 passes
 for (int pass = 0; pass < 100; ++pass)
   for (int door = pass; door < 100; door += pass+1)
     is_open[door] = !is_open[door];
 // output the result
 for (int door = 0; door < 100; ++door)
   std::cout << "door #" << door+1 << (is_open[door]? " is open." : " is closed.") << std::endl;
 return 0;

}</lang>

optimized This optimized version makes use of the fact that finally only the doors with square index are open, as well as the fact that .

<lang cpp>#include <iostream>

int main() {

 int square = 1, increment = 3;
 for (int door = 1; door <= 100; ++door)
 {
   std::cout << "door #" << door;
   if (door == square)
   {
     std::cout << " is open." << std::endl;
     square += increment;
     increment += 2;
   }
   else
     std::cout << " is closed." << std::endl;
 }
 return 0;

}</lang>

The following ultra-short optimized version demonstrates the flexibility of C++ loops, but isn't really considered good C++ style:

<lang cpp>#include <iostream>

int main() {

 for (int door = 1, square = 1, increment = 1; door <= 100; door++ == square && (square += increment += 2))
   std::cout << "door #" << door << (door == square? " is open." : " is closed.") << std::endl;
 return 0;

}</lang>

C#

Unoptimized <lang csharp>using System; class Program {

   static void Main()
   {
       //To simplify door numbers, uses indexes 1 to 100 (rather than 0 to 99)
       bool[] doors = new bool[101];
       for (int pass = 1; pass <= 100; pass++)
           for (int current = pass; current <= 100; current += pass)
               doors[current] = !doors[current];
       for (int i = 1; i <= 100; i++)
           Console.WriteLine("Door #{0} " + (doors[i] ? "Open" : "Closed"), i);
   }

}</lang> Optimized <lang csharp>using System; class Program {

   static void Main()
   {
       int door = 1, inrementer = 0;
       for (int current = 1; current <= 100; current++)
       {
           Console.Write("Door #{0} ", current);
           if (current == door)
           {
               Console.WriteLine("Open");
               inrementer++;
               door += 2 * inrementer + 1;
           }
           else
               Console.WriteLine("Closed");
       }
   }

}</lang>

ColdFusion

Basic Solution: Returns List of 100 values: 1=open 0=closed <lang coldfusion> doorCount = 1; doorList = ""; // create all doors and set all doors to open while (doorCount LTE 100) { doorList = ListAppend(doorList,"1"); doorCount = doorCount + 1; } loopCount = 2; doorListLen = ListLen(doorList); while (loopCount LTE 100) { loopDoorListCount = 1; while (loopDoorListCount LTE 100) { testDoor = loopDoorListCount / loopCount; if (testDoor EQ Int(testDoor)) { checkOpen = ListGetAt(doorList,loopDoorListCount); if (checkOpen EQ 1) { doorList = ListSetAt(doorList,loopDoorListCount,"0"); } else { doorList = ListSetAt(doorList,loopDoorListCount,"1"); } } loopDoorListCount = loopDoorListCount + 1; } loopCount = loopCount + 1; } </lang>

Squares of Integers Solution: Returns List of 100 values: 1=open 0=closed <lang coldfusion> doorCount = 1; doorList = ""; loopCount = 1; while (loopCount LTE 100) { if (Sqr(loopCount) NEQ Int(Sqr(loopCount))) { doorList = ListAppend(doorList,0); } else { doorList = ListAppend(doorList,1); } loopCount = loopCount + 1; } </lang>

Display only <lang coldfusion>

   // Display all doors
   <cfloop from="1" to="100" index="x">
   	Door #x# Open: #YesNoFormat(ListGetAt(doorList,x))#
</cfloop>
   // Output only open doors
   <cfloop from="1" to="100" index="x">
   	<cfif ListGetAt(doorList,x) EQ 1>
       	#x#
</cfif> </cfloop>

</lang>

Common Lisp

Unoptimized / functional This is a very unoptimized version of the problem, using recursion and quite considerable list-copying. It emphatises the functional way of solving this problem

<lang lisp>(defun visit-door (doors doornum value1 value2)

   "visits a door, swapping the value1 to value2 or vice-versa"
   (let ((d (copy-list doors))
         (n (- doornum 1)))
            (if (eq   (nth n d) value1)
                (setf (nth n d) value2)
                (setf (nth n d) value1))
            d))

(defun visit-every (doors num iter value1 value2)

   "visits every 'num' door in the list"
   (if (> (* iter num) (length doors))
       doors
       (visit-every (visit-door doors (* num iter) value1 value2)
                    num
                    (+ 1 iter)
                    value1
                    value2)))

(defun do-all-visits (doors cnt value1 value2)

   "Visits all doors changing the values accordingly"
   (if (< cnt 1)
       doors
       (do-all-visits (visit-every doors cnt 1 value1 value2)
                      (- cnt 1)
                      value1
                      value2)))

(defun print-doors (doors)

   "Pretty prints the doors list"
   (format T "~{~A ~A ~A ~A ~A ~A ~A ~A ~A ~A~%~}~%" doors))

(defun start (&optional (size 100))

   "Start the program"
   (let* ((open "_")
          (shut "#")
          (doors (make-list size :initial-element shut)))
              (print-doors (do-all-visits doors size open shut))))</lang>

Unoptimized / imperative This is a version that closely follows the problem description and is still quite short.

<lang lisp>(define-modify-macro toggle () not)

(defun 100-doors ()

 (let ((doors (make-array 100 :initial-element nil)))
   (dotimes (i 100)
     (loop for j from i below 100 by (1+ i)

do (toggle (svref doors j))))

   (dotimes (i 100)
     (format t "door ~a: ~:[closed~;open~]~%" (1+ i) (svref doors i)))))</lang>

Optimized This is an optimized version of the above, using the perfect square algorithm (Note: This is non-functional as the state of the doors variable gets modified by a function call)

<lang lisp>(defun perfect-square-list (n)

   "Generates a list of perfect squares from 0 up to n"
   (loop for i from 1 to (sqrt n) collect (expt i 2))) 
                

(defun open-door (doors num open)

   "Sets door at num to open"
   (setf (nth (- num 1) doors) open)
   doors) 
                                 

(defun visit-all (doors vlist open)

   "Visits and opens all the doors indicated in vlist"
   (if (null vlist) 
       doors                     
       (visit-all (open-door doors (car vlist) open) 
                  (cdr vlist) 
                  open))) 
                  

(defun start2 (&optional (size 100))

   "Start the program"
   (print-doors (visit-all (make-list size :initial-element "#")
                           (perfect-square-list size) "_")))</lang>

Optimized (2) This version displays a much more functional solution through the use of (mapcar ...)

<lang lisp>(let ((i 0))

   (mapcar (lambda (x)
               (if (zerop (mod (sqrt (incf i)) 1))
                   "_" "#"))
           (make-list 100)))</lang>

Clojure

Unoptimized / mutable array <lang clojure>(defn doors []

 (let [doors (into-array (repeat 100 false))]
   (doseq [pass   (range 1 101) 
           i      (range (dec pass) 100 pass) 
           :while (< i 100)]
     (aset doors i (not (aget doors i))))
   doors))   

(defn open-doors [] (for [[d n] (map vector (doors) (iterate inc 1)) :when d] n))

(defn print-open-doors []

 (println 
   "Open doors after 100 passes:"
   (apply str (interpose ", " (open-doors)))))</lang>

Unoptimized / functional <lang clojure>(defn doors []

 (reduce (fn [doors toggle-idx] (update-in doors [toggle-idx] not))
         (into [] (repeat 100 false))
         (for [pass   (range 1 101)
               i      (range (dec pass) 100 pass)
               :while (< i 100)]
           i)))

(defn open-doors [] (for [[d n] (map vector (doors) (iterate inc 1)) :when d] n))

(defn print-open-doors []

 (println 
   "Open doors after 100 passes:"
   (apply str (interpose ", " (open-doors)))))</lang>

Optimized / functional <lang clojure>(defn doors [] (reduce (fn [doors idx] (assoc doors idx true)) (into [] (repeat 100 false)) (map #(dec (* % %)) (range 1 11))))

(defn open-doors [] (for [[d n] (map vector (doors) (iterate inc 1)) :when d] n))

(defn print-open-doors []

 (println 
   "Open doors after 100 passes:"
   (apply str (interpose ", " (open-doors)))))</lang>

D

<lang d>import std.stdio: write, writeln;

enum DoorState : uint { Closed, Open } alias DoorState[] Doors;

Doors flipUnoptimized(Doors doors) {

   doors[] = DoorState.Closed;
   foreach (i; 0 .. doors.length)
       for (int j = i; j < doors.length; j += i+1)
           if (doors[j] == DoorState.Open)
               doors[j] = DoorState.Closed;
           else
               doors[j] = DoorState.Open;
   return doors;

}

Doors flipOptimized(Doors doors) {

   doors[] = DoorState.Closed;
   for (int i = 1; i*i <= doors.length; i++)
       doors[i*i - 1] = DoorState.Open;
   return doors;

}

// test program void main() {

   auto doors = new Doors(100);
   foreach (i, door; flipUnoptimized(doors))
       if (door == DoorState.Open)
           write(i+1, " ");
   writeln();
   foreach (i, door; flipOptimized(doors))
       if (door == DoorState.Open)
           write(i+1, " ");
   writeln();

}</lang>

Dylan

Unoptimized <lang dylan>define method doors()

 let doors = make(<array>, fill: #f, size: 100);
 for (x from 0 below 100)
   for (y from x below 100 by x + 1)
     doors[y] := ~doors[y]
   end
 end;
 for (x from 1 to 100) 
   if (doors[x - 1]) 
     format-out("door %d open\n", x)
   end
 end

end</lang>

E

Graphical

Works with: E-on-Java

This version animates the changes of the doors (as checkboxes).

<lang e>#!/usr/bin/env rune

var toggles := [] var gets := []

  1. Set up GUI (and data model)

def frame := <swing:makeJFrame>("100 doors") frame.getContentPane().setLayout(<awt:makeGridLayout>(10, 10)) for i in 1..100 {

 def component := <import:javax.swing.makeJCheckBox>(E.toString(i))
 toggles with= fn { component.setSelected(!component.isSelected()) }
 gets with= fn { component.isSelected() }
 frame.getContentPane().add(component)

}

  1. Set up termination condition

def done frame.addWindowListener(def _ {

 to windowClosing(event) {
   bind done := true
 }
 match _ {}

})

  1. Open and close doors

def loop(step, i) {

 toggles[i] <- ()
 def next := i + step
 timer.whenPast(timer.now() + 10, fn {
   if (next >= 100) {
     if (step >= 100) {
       # Done.
     } else {
       loop <- (step + 1, step)
     }
   } else {
     loop <- (step, i + step)
   }    
 })

} loop(1, 0)

frame.pack() frame.show() interp.waitAtTop(done)</lang>

Emacs Lisp

Unoptimized

<lang lisp>(defun create-doors ()

 "Returns a list of closed doors

Each door only has two status: open or closed. If a door is closed it has the value 0, if it's open it has the value 1."

 (let ((return_value '(0))
        ;; There is already a door in the return_value, so k starts at 1
        ;; otherwise we would need to compare k against 99 and not 100 in
        ;; the while loop
        (k 1))
   (while (< k 100)
     (setq return_value (cons 0 return_value))
     (setq k (+ 1 k)))
   return_value))

(defun toggle-single-door (doors)

 "Toggle the stat of the door at the `car' position of the DOORS list

DOORS is a list of integers with either the value 0 or 1 and it represents a row of doors.

Returns a list where the `car' of the list has it's value toggled (if open it becomes closed, if closed it becomes open)."

 (if (= (car doors) 1)
   (cons 0 (cdr doors))
   (cons 1 (cdr doors))))

(defun toggle-doors (doors step original-step)

 "Step through all elements of the doors' list and toggle a door when step is 1

DOORS is a list of integers with either the value 0 or 1 and it represents a row of doors. STEP is the number of doors we still need to transverse before we arrive at a door that has to be toggled. ORIGINAL-STEP is the value of the argument step when this function is called for the first time.

Returns a list of doors"

 (cond ((null doors)
         '())
   ((= step 1)
     (cons (car (toggle-single-door doors))
       (toggle-doors (cdr doors) original-step original-step)))
   (t
     (cons (car doors)
       (toggle-doors (cdr doors) (- step 1) original-step)))))

(defun main-program ()

 "The main loop for the program"
 (let ((doors_list (create-doors))
        (k 1)
        ;; We need to define max-specpdl-size and max-specpdl-size to big
        ;; numbers otherwise the loop reaches the max recursion depth and
        ;; throws an error.
        ;; If you want more information about these variables, press Ctrl
        ;; and h at the same time and then press v and then type the name
        ;; of the variable that you want to read the documentation.
        (max-specpdl-size 5000)
        (max-lisp-eval-depth 2000))
   (while (< k 101)
     (setq doors_list (toggle-doors doors_list k k))
     (setq k (+ 1 k)))
   doors_list))

(defun print-doors (doors)

 "This function prints the values of the doors into the current buffer.

DOORS is a list of integers with either the value 0 or 1 and it represents a row of doors. "

 ;; As in the main-program function, we need to set the variable
 ;; max-lisp-eval-depth to a big number so it doesn't reach max recursion
 ;; depth.
 (let ((max-lisp-eval-depth 5000))
   (unless (null doors)
     (insert (int-to-string (car doors)))
     (print-doors (cdr doors)))))
Returns a list with the final solution

(main-program)

Print the final solution on the buffer

(print-doors (main-program))</lang>

Erlang

optimized <lang erlang>doors() ->

    F = fun(X) -> Root = math:pow(X,0.5), Root == trunc(Root) end,
    Out = fun(X, true) -> io:format("Door ~p: open~n",[X]);
             (X, false)-> io:format("Door ~p: close~n",[X]) end,
    [Out(X,F(X)) || X <- lists:seq(1,100)].</lang>

Factor

<lang Factor>USING: bit-arrays formatting fry kernel math math.ranges sequences ; IN: rosetta.doors

CONSTANT: number-of-doors 100

multiples ( n -- range )
   0 number-of-doors rot <range> ;
toggle-multiples ( n doors -- )
   [ multiples ] dip '[ _ [ not ] change-nth ] each ;
toggle-all-multiples ( doors -- )
   [ number-of-doors [1,b] ] dip '[ _ toggle-multiples ] each ;
print-doors ( doors -- )
   [
       swap "open" "closed" ? "Door %d is %s\n" printf
   ] each-index ;
main ( -- )
   number-of-doors 1 + <bit-array>
   [ toggle-all-multiples ] [ print-doors ] bi ;</lang>

Falcon

Unoptimized code <lang falcon>doors = arrayBuffer( 101, false )

for pass in [ 0 : doors.len() ]

 for door in [ 0 : doors.len() : pass+1 ]
   doors[ door ] = not doors[ door ]
 end

end

for door in [ 1 : doors.len() ] // Show Output

 >  "Door ", $door, " is: ", ( doors[ door ] ) ? "open" : "closed"

end </lang> Optimized code <lang falcon> for door in [ 1 : 101 ]: > "Door ", $door, " is: ", fract( door ** 0.5 ) ? "closed" : "open"</lang>

Forth

The problem with unfactored code is it's difficult to follow. The included example works, but to comprehend the code, you're mentally juggling items on the return stack (e.g., i, j) as well as items on the data stack, plus whatever is in dictionary space. Since people can only keep seven things in his or her mind, plus or minus two, this quickly becomes an intellectual burden. This style of coding typifies Forth software development in the mid-70s and -80s, which resulted in Forth's undeserved "write-only language" reputation.

The well-factored code works much better from a readability point of view (assuming familiarity with Forth's coding conventions), but without the aid of an optimizing compiler, can suffer from slower execution performance and somewhat larger memory consumption.

Of course, this size/speed tradeoff appears in many languages, not just Forth.

Factored <lang forth>100 constant /doors create 'doors

   /doors allot

'doors /doors + constant <doors

toggle 1 over c@ xor swap c! ;
pass dup 1- 'doors + begin dup <doors < while dup toggle over + repeat 2drop ;
passes /doors 1 begin 2dup >= while dup pass 1+ repeat 2drop ;
.closed over c@ if over 'doors - 1+ . then ;
report 'doors /doors begin dup while .closed 1 /string repeat cr 2drop ;
open 'doors /doors erase ;
doors open passes report ;</lang>

Unfactored <lang 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</lang>

Optimized <lang forth>: SQUARED DUP * ;

DOORS 1 BEGIN 2DUP SQUARED >= WHILE DUP SQUARED . 1+ REPEAT 2DROP ;

100 DOORS</lang>

Fortran

Works with: Fortran version ISO 90 and later

unoptimized <lang fortran>PROGRAM DOORS

 INTEGER, PARAMETER :: n = 100    ! Number of doors
 INTEGER :: i, j
 LOGICAL :: door(n) = .TRUE.      ! Initially closed

 DO i = 1, n
   DO j = i, n, i
     door(j) = .NOT. door(j)
   END DO
 END DO 
 DO i = 1, n
   WRITE(*,"(A,I3,A)", ADVANCE="NO") "Door ", i, " is "
   IF (door(i)) THEN
     WRITE(*,"(A)") "closed"
   ELSE
     WRITE(*,"(A)") "open"
   END IF
 END DO

END PROGRAM DOORS</lang>

optimized <lang fortran>PROGRAM DOORS

 INTEGER, PARAMETER :: n = 100    ! Number of doors
 INTEGER :: i
 LOGICAL :: door(n) = .TRUE.      ! Initially closed

 DO i = 1, SQRT(REAL(n))
   door(i*i) = .FALSE.
 END DO  

 DO i = 1, n
   WRITE(*,"(A,I3,A)", ADVANCE="NO") "Door ", i, " is "
   IF (door(i)) THEN
     WRITE(*,"(A)") "closed"
   ELSE
     WRITE(*,"(A)") "open"
   END IF
 END DO

END PROGRAM DOORS</lang>

F#

Requires #light in versions of F# prior to 2010 beta. <lang fsharp>let answerDoors =

   let ToggleNth n (lst:bool array) =                  // Toggle every n'th door
       [(n-1) .. n .. 99]                              // For each appropriate door
       |> Seq.iter (fun i -> lst.[i] <- not lst.[i])   // toggle it
   let doors = Array.create 100 false                  // Initialize all doors to closed
   Seq.iter (fun n -> ToggleNth n doors) [1..100]      // toggle the appropriate doors for each pass
   doors                                               // Initialize all doors to closed

</lang> Following is the solution using perfect squares. The coercions in PerfectSquare are, I believe, slightly different in versions prior to 2010 beta and, again, #light is required in those versions. <lang fsharp>open System let answer2 =

   let PerfectSquare n =
       let sqrt = int(Math.Sqrt(float n))
       n = sqrt * sqrt
   [| for i in 1..100 do yield PerfectSquare i |]</lang>

Go

unoptimized <lang go>package main

import ( . "fmt"; )

func main() { doors := make([]bool, 100);

for pass := 0; pass <= 100; pass++ { for door := pass; door < 100; door += pass + 1 { doors[door] = !doors[door] } }

for i, v := range doors { if v { Printf("1") } else { Printf("0") }

if i%10 == 9 { Printf("\n") } else { Printf(" ") }

} }</lang>


optimized <lang go>package main

import ( . "fmt" )

func main() { var door int = 1 var incrementer = 0

for current := 1; current <= 100; current++ { Printf("Door %d ", current)

if current == door { Printf("Open\n") incrementer++ door += 2 * incrementer + 1 } else { Printf("Closed\n") } } }</lang>

Groovy

unoptimized <lang groovy>doors = [false] * 100 (0..99).each {

  it.step(100, it + 1) {
     doors[it] ^= true
  }

} (0..99).each {

  println("Door #${it + 1} is ${doors[it] ? 'open' : 'closed'}.")

}</lang>

optimized a Using square roots

<lang groovy>(1..100).each {

  println("Door #${it} is ${Math.sqrt(it).with{it==(int)it} ? 'open' : 'closed'}.")

}</lang>

optimized b Without using square roots <lang groovy>doors = ['closed'] * 100 (1..10).each { doors[it**2 - 1] = 'open' } (0..99).each {

  println("Door #${it + 1} is ${doors[it]}.")

}</lang>

Haskell

unoptimized <lang haskell>data Door = Open | Closed deriving Show

toggle Open = Closed toggle Closed = Open

pass k = zipWith ($) (cycle $ replicate k id ++ [toggle])

run n = foldl (flip pass) (replicate n Closed) [0..n]</lang>

optimized (without using square roots) <lang haskell>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..]]</lang>

alternatively, returning a list of all open gates, it's a one-liner:

<lang haskell>run n = takeWhile (< n) [k*k | k <- [1..]]</lang>

haXe

<lang haxe>class RosettaDemo {

   static public function main()
   {
       findOpenLockers(100);
   }
   static function findOpenLockers(n : Int)
   {
       var i = 1;
       while((i*i) <= n)
       {
           neko.Lib.print(i*i + "\n");
           i++;
       }
   }

}</lang>

HicEst

Unoptimized <lang hicest>REAL :: n=100, open=1, door(n)

door = 1 - open ! = closed DO i = 1, n

 DO j = i, n, i
   door(j) = open - door(j)
 ENDDO

ENDDO DLG(Text=door, TItle=SUM(door)//" doors open") </lang> Optimized <lang hicest>door = 1 - open ! = closed DO i = 1, n^0.5

 door(i*i) = open

ENDDO DLG(Text=door, TItle=SUM(door)//" doors open") </lang>

Icon and Unicon

Icon

Unoptimized solution. <lang icon> procedure main()

   door := table(0)    # default value of entries is 0
   every pass := 1 to 100 do
       every door[i := pass to 100 by pass] := 1 - door[i]
   every write("Door ", i := 1 to 100, " is ", if door[i] = 1 then "open" else "closed")

end </lang>

Optimized solution. <lang icon> procedure main()

   every write("Door ", i := 1 to 100, " is ", if integer(sqrt(i)) = sqrt(i) then "open" else "closed")

end </lang>

or

<lang icon>procedure main(args)

   dMap := table("closed")
   every dMap[(1 to sqrt(100))^2] := "open"
   every write("Door ",i := 1 to 100," is ",dMap[i])

end</lang>

Unicon

The Icon solutions also work in Unicon.

Notes:

  • Icon and Unicon don't have a boolean type because most often, logic is expressed in terms of success or failure, which affects flow at runtime.

Io

simple boolean list solution: <lang io> doors := List clone for(i,1,100, doors append(false)) for(i,1,100,

   for(x,i,100, i, doors atPut(x - 1, doors at(x - 1) not))

) doors foreach(i, x, if(x, "Door #{i + 1} is open" interpolate println)) </lang>

Ioke

Unoptimized Object Oriented solution. <lang ioke>NDoors = Origin mimic

NDoors Toggle = Origin mimic do(

 initialize = method(toggled?, @toggled? = toggled?)
 toggle! = method(@toggled? = !toggled?. self)

)

NDoors Doors = Origin mimic do(

 initialize = method(n,
   @n = n
   @doors = {} addKeysAndValues(1..n, (1..n) map(_, NDoors Toggle mimic(false)))
 )
 numsToToggle = method(n, for(x <- (1..@n), (x % n) zero?, x))
 toggleThese = method(nums, nums each(x, @doors[x] = @doors at(x) toggle))
 show = method(@doors filter:dict(value toggled?) keys sort println)

)

Test code

x = NDoors Doors mimic(100) (1..100) each(n, x toggleThese(x numsToToggle(n))) x show</lang>

J

unoptimized <lang j> ~:/ (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 ...

  ~:/ 0=|/~ >:i.100  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 ...</lang> optimized <lang j> (>: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 ...</lang>

Java

unoptimized <lang java> public class Door {

private boolean open = false; private final int index;

public Door(int index) { this.index = index; }

public int getIndex() { return index; }

public String getState() { return open ? "open" : "closed"; }

public void toggle() { open = !open; }

public static void main(String[] args) { final int N = 100; Door[] doors = new Door[N]; for (int i = 0; i < N; i++) { doors[i] = new Door(i + 1); } for (int pass = 1; pass <= N; pass++) { for (Door door : doors) { if (door.getIndex() % pass == 0) { door.toggle(); } } } for (Door door : doors) { System.out.println("Door #" + door.getIndex() + " is " + door.getState() + "."); } } } </lang>

optimized <lang java>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.")); } } }</lang>

JavaScript

Works with: SpiderMonkey

for the print() statement.

<lang javascript>var CLOSED = 0; var OPEN = 1; var n = 100; var doors = new Array(n);

// initialize doors for (var i = 0; i < n; i++)

   doors[i] = CLOSED;

// now, start opening and closing for (var step = 1; step < n; step ++)

   for (var idx = step; idx < n; idx += step) 
       // toggle state of door
       doors[idx] =  (doors[idx] == OPEN ? CLOSED : OPEN)    

// find out which doors are open for (i = 0; i < n; i++)

   if (doors[i] == OPEN)
       print("door " + i + " is open.");</lang>

outputs

door 1 is open.
door 4 is open.
door 9 is open.
door 16 is open.
door 25 is open.
door 36 is open.
door 49 is open.
door 64 is open.
door 81 is open.

Using features of JavaScript 1.6, this

Works with: Firefox version 1.5

<lang javascript>var n = 100; var doors = new Array(n); doors.forEach(function(val, idx, ary) {ary[idx] = 0});

// now, start opening and closing for (var step = 1; step < n; step ++)

   for (var idx = step; idx < n; idx += step) 
       // toggle state of door
       doors[idx] =  !doors[idx];

// find out which doors are open var open = doors.reduce(function(open, val, idx) {if (val) open.push(idx); return open}, []) print("these doors are open: " + open.join(','));</lang> outputs

these doors are open: 1,4,9,16,25,36,49,64,81


K

unoptimized / converted from Q . <lang k> `closed `open ![ ; 2 ] @ #:' 1 _ = ,/ &:' 0 = t !\:/: t : ! 101</lang>

optimized / 1 origin indices <lang k> ( 1 + ! 10 ) ^ 2</lang>

/ As parameterized function : <lang k> { ( 1 + ! _ x ^ % 2 ) ^ 2 } 100 </lang>

<lang Logo>to doors

Problem 100 Doors
FMSLogo
lrcvs 2010

make "door (vector 100 1) for [p 1 100][setitem :p :door 0]

for [a 1 100 1][for [b :a 100 :a][make "x item :b :door ifelse :x = 0 [setitem :b :door 1][setitem :b :door 0] ] ]

for [c 1 100][make "y item :c :door ifelse :y = 0 [pr (list :c "Close)] [pr (list :c "Open)] ] end</lang>

Lua

<lang lua>is_open = {}

for door = 1,100 do is_open[door] = false end

for pass = 1,100 do

   for door = pass,100,pass do
       is_open[door] = not is_open[door]
   end

end

for i,v in next,is_open do

   if v then
       print ('Door '..i..':','open')
   else
       print ('Door '..i..':', 'close')
   end

end</lang>

M4

<lang m4>define(`_set', `define(`$1[$2]', `$3')')dnl define(`_get', `defn(`$1[$2]')')dnl define(`for',`ifelse($#,0,``$0,`ifelse(eval($2<=$3),1, `pushdef(`$1',$2)$5`'popdef(`$1')$0(`$1',eval($2+$4),$3,$4,`$5')')')')dnl define(`opposite',`_set(`door',$1,ifelse(_get(`door',$1),`closed',`open',`closed'))')dnl define(`upper',`100')dnl for(`x',`1',upper,`1',`_set(`door',x,`closed')')dnl for(`x',`1',upper,`1',`for(`y',x,upper,x,`opposite(y)')')dnl for(`x',`1',upper,`1',`door x is _get(`door',x) ')dnl</lang>

Mathematica

unoptimized 1 <lang mathematica>n=100; tmp=ConstantArray[-1,n]; Do[tmpi;;;;i*=-1;,{i,n}]; Do[Print["door ",i," is ",If[tmpi==-1,"closed","open"]],{i,1,Length[tmp]}]</lang>

optimized 1 <lang mathematica>Do[Print["door ",i," is ",If[IntegerQ[Sqrt[i]],"open","closed"]],{i,100}]</lang>

optimized 2 <lang mathematica>n=100; a=Range[1,Sqrt[n]]^2 Do[Print["door ",i," is ",If[MemberQ[a,i],"open","closed"]],{i,100}]</lang>

optimized 3 <lang mathematica>n=100 nn=1 a=0 For[i=1,i<=n,i++,

If[i==nn,
 Print["door ",i," is open"];
 a++;
 nn+=2a+1;
,
 Print["door ",i," is closed"];
];

]</lang>

These will only give the indices for the open doors: unoptimized 2 <lang mathematica>Pick[Range[100], Xor@@@Array[Divisible[#1,#2]&, {100,100}]]</lang>

optimized 4 <lang mathematica>Range[Sqrt[100]]^2</lang>

MATLAB

Iterative Method

Unoptimized <lang MATLAB> a=zeros(1,100); for b=1:100; for i=b:b:100;

   if a(i)==1
       a(i)=0;
   else 
       a(i)=1;
   end

end end a </lang> Optimized <lang MATLAB> for x=1:100;

 if sqrt(x) == floor(sqrt(x))
   a(i)=1;
 end

end a </lang>

Vectorized Method

<lang MATLAB>function [doors,opened,closed] = hundredDoors()

   %Initialize the doors, make them booleans for easy vectorization
   doors = logical( (1:1:100) );
   
   %Go through the flipping process, ignore the 1 case because the doors
   %array is already initialized to all open
   for initialPosition = (2:100)
       doors(initialPosition:initialPosition:100) = not( doors(initialPosition:initialPosition:100) );
   end
   
   opened = find(doors); %Stores the numbers of the open doors
   closed = find( not(doors) ); %Stores the numbers of the closed doors
   

end</lang>

MAXScript

unoptimized <lang maxscript>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]

)</lang> optimized <lang maxscript>for i in 1 to 100 do (

   root = pow i 0.5
   format ("Door % is open?: %\n") i (root == (root as integer))

)</lang>

Metafont

<lang metafont>boolean doors[]; for i = 1 upto 100: doors[i] := false; endfor for i = 1 upto 100:

 for j = 1 step i until 100:
   doors[j] := not doors[j];
 endfor

endfor for i = 1 upto 100:

 message decimal(i) & " " & if doors[i]: "open" else: "close" fi;

endfor end</lang>

MMIX

See 100 doors/MMIX

Modula-3

unoptimized <lang modula3>MODULE Doors EXPORTS Main;

IMPORT IO, Fmt;

TYPE State = {Closed, Open}; TYPE List = ARRAY [1..100] OF State;

VAR doors := List{State.Closed, ..};

BEGIN

 FOR i := 1 TO 100 DO
   FOR j := FIRST(doors) TO LAST(doors) DO
     IF j MOD i = 0 THEN
       IF doors[j] = State.Closed THEN
         doors[j] := State.Open;
       ELSE
         doors[j] := State.Closed;
       END;
     END;
   END;
 END;
 FOR i := FIRST(doors) TO LAST(doors) DO
   IO.Put(Fmt.Int(i) & " is ");
   IF doors[i] = State.Closed THEN
     IO.Put("Closed.\n");
   ELSE
     IO.Put("Open.\n");
   END;
 END;

END Doors.</lang>

optimized

<lang modula3>MODULE DoorsOpt EXPORTS Main;

IMPORT IO, Fmt;

TYPE State = {Closed, Open}; TYPE List = ARRAY [1..100] OF State;

VAR doors := List{State.Closed, ..};

BEGIN

 FOR i := 1 TO 10 DO
   doors[i * i] := State.Open;
 END;
 FOR i := FIRST(doors) TO LAST(doors) DO
   IO.Put(Fmt.Int(i) & " is ");
   IF doors[i] = State.Closed THEN
     IO.Put("Closed.\n");
   ELSE
     IO.Put("Open.\n");
   END;
 END;

END DoorsOpt.</lang>

MOO

<lang moo>is_open = make(100); for pass in [1..100]

 for door in [pass..100]
   if (door % pass)
     continue;
   endif
   is_open[door] = !is_open[door];
 endfor

endfor

"output the result"; for door in [1..100]

 player:tell("door #", door, " is ", (is_open[door] ? "open" : "closed"), ".");

endfor</lang>


MUMPS

<lang <MUMPS>doors new door,pass For door=1:1:100 Set door(door)=0 For pass=1:1:100 For door=pass:pass:100 Set door(door)='door(door) For door=1:1:100 If door(door) Write !,"Door",$j(door,4)," is open" Write !,"All other doors are closed." Quit Do doors Door 1 is open Door 4 is open Door 9 is open Door 16 is open Door 25 is open Door 36 is open Door 49 is open Door 64 is open Door 81 is open Door 100 is open All other doors are closed.</lang>

Objeck

optimized <lang objeck> bundle Default {

 class Doors {
   function : Main(args : String[]) ~ Nil {
     doors := Bool->New[100];
     
     for(pass := 0; pass < 10; pass += 1;) {
       doors[(pass + 1) * (pass + 1) - 1] := true;
     };
     
     for(i := 0; i < 100; i += 1;) {    
       IO.Console->GetInstance()->Print("Door #")->Print(i + 1)->Print(" is ");
       if(doors[i]) {
         "open."->PrintLine();
       }
       else {
         "closed."->PrintLine();
       };
     };
   }
 }

} </lang>

OCaml

unoptimized <lang ocaml>let max_doors = 100

let show_doors =

 Array.iteri (fun i x -> Printf.printf "Door %d is %s\n" (i+1)
                                       (if x then "open" else "closed"))

let flip_doors doors =

 for i = 1 to max_doors do
   let rec flip idx =
     if idx < max_doors then begin
       doors.(idx) <- not doors.(idx);
       flip (idx + i)
     end
   in flip (i - 1)
 done;
 doors

let () =

 show_doors (flip_doors (Array.make max_doors false))</lang>

optimized <lang ocaml>let optimised_flip_doors doors =

 for i = 1 to int_of_float (sqrt (float_of_int max_doors)) do
   doors.(i*i - 1) <- true
 done;
 doors

let () =

 show_doors (optimised_flip_doors (Array.make max_doors false))</lang>

Octave

<lang octave>doors = false(100,1); for i = 1:100

 for j = i:i:100
   doors(j) = !doors(j);
 endfor

endfor for i = 1:100

 if ( doors(i) )
   s = "open";
 else
   s = "closed";
 endif
 printf("%d %s\n", i, s);

endfor</lang>

Oz

<lang oz>declare

 NumDoors = 100
 NumPasses = 100
 fun {NewDoor} closed end
 fun {Toggle Door}
    case Door of closed then open
    [] open then closed
    end
 end
 fun {Pass Doors I}
    {List.mapInd Doors
     fun {$ Index Door}
        if Index mod I == 0 then {Toggle Door}
        else Door
        end
     end}
 end
 
 Doors0 = {MakeList NumDoors}
 {ForAll Doors0 NewDoor}
 DoorsN = {FoldL {List.number 1 NumPasses 1} Pass Doors0}

in

 %% print open doors
 {List.forAllInd DoorsN
  proc {$ Index Door}
     if Door == open then

{System.showInfo "Door "#Index#" is open."}

     end
  end
 }</lang>

Output:

Door 1 is open.
Door 4 is open.
Door 9 is open.
Door 16 is open.
Door 25 is open.
Door 36 is open.
Door 49 is open.
Door 64 is open.
Door 81 is open.
Door 100 is open.

Pascal

<lang pascal>Program OneHundredDoors;

var

  doors : Array[1..100] of Boolean;
  i, j	 : Integer;
  

begin

  for i := 1 to 100 do
     doors[i] := False;
  for i := 1 to 100 do begin
     j := i;
     while j <= 100 do begin

doors[j] := not doors[j]; j := j + i

     end
  end;
  for i := 1 to 100 do begin
     Write(i, ' ');
     if doors[i] then

WriteLn('open')

     else

WriteLn('closed');

  end

end.</lang>

PHP

optimized <lang php><?php for ($i = 1; $i <= 100; $i++) { $root = sqrt($i); $state = ($root == ceil($root)) ? "open" : "closed"; echo "Door $i: $state"; } ?></lang>

Perl

unoptimized

Works with: Perl version 5.x

<lang perl>my @doors; for my $pass (1 .. 100) {

   for (1 .. 100) {
       if (0 == $_ % $pass) {
           $doors[$_] = not $doors[$_];
       };
   };

};

print "Door $_ is", $doors[$_] ? "open" : "closed", "\n" for 1 .. 100;</lang>

optimized

Works with: Perl version 5.x

<lang perl>print "Door $_ is ", qw"closed open"[int sqrt == sqrt], "\n" for 1..100;</lang> <lang perl>while( ++$i <= 100 ) {

   $root = sqrt($i);
   if ( int( $root ) == $root )
   {
       print "Door $i is open\n";
   }
   else
   {
       print "Door $i is closed\n";
   }

}</lang>

Perl 6

unoptimized

Works with: Rakudo version 2010.07"

<lang perl6>my @doors = False xx 101;

($_ = !$_ for @doors[0, *+$_ ... 100]) for 1..100;

say "Door $_ is ", <closed open>[ @doors[$_] ] for 1..100;</lang>

optimized

Works with: Rakudo version #25 "Minneapolis"

<lang perl6>say "Door $_ is open" for map * ** 2, 1..10;</lang>

or printing both opened and closed doors:

<lang perl6>say "Door $_ is ", <closed open>[.sqrt == .sqrt.floor] for 1..100;</lang>

PicoLisp

unoptimized <lang PicoLisp>(let Doors (need 100)

  (for I 100
     (for (D (nth Doors I)  D  (cdr (nth D I)))
        (set D (not (car D))) ) )
  (println Doors) )</lang>

optimized <lang PicoLisp>(let Doors (need 100)

  (for I (sqrt 100)
     (set (nth Doors (* I I)) T) )
  (println Doors) )</lang>

Output in both cases:

(T NIL NIL T NIL NIL NIL NIL T NIL NIL NIL NIL NIL NIL T NIL NIL NIL NIL NIL NIL
 NIL NIL T NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL T NIL NIL NIL NIL NIL NIL NIL
 NIL NIL NIL NIL NIL T NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL T
 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL T NIL NIL NIL N
IL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL T)

PL/I

<lang PL/I> declare door(100) bit (1) aligned; declare closed bit (1) static initial ('0'b),

       open   bit (1) static initial ('1'b);

declare (i, inc) fixed binary;

door = closed; inc = 1; do until (inc >= 100);

  do i = inc to 100 by inc;
     door(i) = ^door(i); /* close door if open; open it if closed. */
  end;
  inc = inc+1;

end;

do i = 1 to 100;

  put skip edit ('Door ', trim(i), ' is ') (a);
  if door(i) then put edit (' open.') (a);
  else put edit (' closed.') (a);

end; </lang>

Pop11

unoptimized <lang pop11>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;</lang>

optimized <lang pop11>for i to 100 do

   lvars root = sqrt(i);
   i; if root = round(root) then ' open' ><; else ' closed' ><; endif; =>

endfor;</lang>

PowerShell

unoptimized <lang powershell>$doors = @(0..99) for($i=0; $i -lt 100; $i++) {

 $doors[$i] = 0  # start with all doors closed

} for($i=0; $i -lt 100; $i++) {

 $step = $i + 1
 for($j=$i; $j -lt 100; $j = $j + $step) {
   $doors[$j] = ($doors[$j] + 1)  % 2
 }

} foreach($doornum in 1..100) {

 if($doors[($doornum-1)] -eq $true) {"$doornum open"}
 else {"$doornum closed"}

}</lang>

PureBasic

unoptimized <lang purebasic>Dim doors.b(100)

For x = 1 To 100

 y = x
 While y <= 100
   If doors(y)
     doors(y) = 0
   Else
     doors(y) = 1
   EndIf
   y + x
 Wend

Next

OpenConsole() PrintN("Following Doors are open:") For x = 1 To 100

 If doors(x)
   Print(Str(x)+", ")
 EndIf

Next Input()</lang>

optimized <lang PureBasic>OpenConsole() PrintN("Following Doors are open:") For i = 1 To 100

   root.f = Pow(i,0.5)
   If root = Int(root)
   	Print (Str(i) + ", ")
   EndIf

Next Input()</lang>


Output:

Following Doors are open:
1, 4, 9, 16, 25, 36, 49, 64, 81, 100,

Python

Works with: Python version 2.5+

unoptimized <lang python>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'

</lang>

optimized

A version that only visits each door once:

<lang python>for i in xrange(1, 101):

   root = i ** 0.5
   print "Door %d:" % i, 'open' if root == int(root) else 'close'</lang>

Q

unoptimized <lang q>`closed`open mod[;2]count each 1 _ group raze where each 0=t mod\:/:t:til 101</lang>

R

unoptimized <lang r>doors_puzzle <- function(ndoors=100,passes=100) {

   doors <- rep(FALSE,ndoors)
   for (ii in seq(1,passes)) {
       mask <- seq(0,ndoors,ii)
       doors[mask] <- !doors[mask]	
   }
   return (which(doors == TRUE))

}

doors_puzzle()</lang>

optimized <lang r>## optimized version... we only have to to up to the square root of 100 seq(1,sqrt(100))**2</lang>

REBOL

<lang rebol>doors: array/initial 100 'open forskip doors 2 [ change next doors 'closed ] if error? try [

   forskip doors 3 [ state: third doors poke doors 3 either state = 'open [ 'closed ] [ 'open ] ]

] [ doors: head doors ]</lang>


REXX

<lang rexx>door. = 0 do inc = 1 to 100

 do d = inc to 100 by inc
   door.d = \door.d
 end

end say "The open doors after 100 passes:" do i = 1 to 100

 if door.i = 1 then say i

end</lang>

Ruby

unoptimized <lang ruby>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

}</lang>

optimized <lang ruby>n = 100 (1..n).each do |i|

   puts "Door #{i} is #{i**0.5 == (i**0.5).round ? "open" : "closed"}"

end </lang>

Sather

<lang sather>class MAIN is

 main is
   pass, door :INT;
   doors :ARRAY{BOOL} := #(100);
   loop 
     doors[0.upto!(99)] := false;
   end;
   pass := 0;
   loop while!(pass < 100);
     door := pass;
     loop while! (door < 100);
       doors[door] := ~doors[door];

door := door + pass + 1

     end;
     pass := pass + 1;
   end;
   loop
     door := 0.upto!(99);
     #OUT + (door+1) + " " + doors[door] + "\n";
   end;
 end;

end;</lang>

SAS

<lang sas>data _null_;

  open=1;
  close=0;
  array Door{100};
  do Pass = 1 to 100;
     do Current = 1 to 100 by Pass;
        if Door{Current} ne open 
           then Door{Current} = open;
           else Door{Current} = close;
     end;
  end;
  NumberOfOpenDoors = sum(of Door{*});
  put "Number of Open Doors:  " NumberOfOpenDoors; 

run;</lang>

Scala

Both optimized and non-optimized versions follow. Both are fully functional.

<lang scala>object HundredDoors {

 sealed abstract class DoorState { def toggle: DoorState }
 case object Opened extends DoorState { def toggle = Closed }
 case object Closed extends DoorState { def toggle = Opened }
 case class Door(number: Int, state: DoorState = Closed) {
   override def toString = "Door "+number+" is "+state
   def toggle = this.copy(state = state.toggle)
 }
 def unoptimized {
   val doors = 1 to 100 map (Door(_))
   (1 to 100).foldLeft(doors)((doors, pass) =>
     doors map (door =>
       if (door.number % pass == 0) door.toggle else door
     )
   ) foreach println
 }
 def optimized {
   val openedDoorNumbers = Set(1 to 10 map (n => n * n): _*)
   1 to 100 map (n => if (openedDoorNumbers contains n) Door(n, Opened) else Door(n)) foreach println
 }

}</lang>

Scheme

unoptimized <lang scheme>(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)))</lang>

optimized <lang scheme>(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)))</lang>

Slate

Unoptimized <lang slate>define: #a -> (Array newSize: 100). a infect: [| :_ | False].

a keysDo: [| :pass |

 pass to: a indexLast by: pass do: [| :door |
   a at: door infect: #not `er]].

a keysAndValuesDo: [| :door :isOpen |

 inform: 'door #' ; door ; ' is ' ; (isOpen ifTrue: ['open'] ifFalse: ['closed'])].</lang>

Optimized <lang slate>define: #a -> (Array newSize: 100). a infect: [| :_ | False].

0 below: 10 do: [| :door | a at: door squared put: True]. a keysAndValuesDo: [| :door :isOpen |

 inform: 'door #' ; door ; ' is ' ; (isOpen ifTrue: ['open'] ifFalse: ['closed'])].</lang>

Smalltalk

Works with: GNU Smalltalk

Unoptimized <lang smalltalk>|a| a := Array new: 100 . 1 to: 100 do: [ :i | a at: i put: false ].

1 to: 100 do: [ :pass |

 pass to: 100 by: pass do: [ :door |
   a at: door put: (a at: door) not .
 ]

].

"output" 1 to: 100 do: [ :door |

  ( 'door #%1 is %2' %
    { door . (a at: door) ifTrue: [ 'open' ] ifFalse: [ 'closed' ] } ) displayNl

]</lang> Optimized

<lang smalltalk>|a| a := (1 to: 100) collect: [ :x | false ]. 1 to: 10 do: [ :i | a at: (i squared) put: true ]. 1 to: 100 do: [ :i |

  ( 'door #%1 is %2' % { i . 
          (a at: i) ifTrue: [ 'open' ] 
                    ifFalse: [ 'closed' ] }
  ) displayNl

]</lang>

Works with: Squeak Smalltalk

Unoptimized, using Morphs <lang smalltalk> | m w h smh smw delay closedDoor border subMorphList |

closedDoor := Color black. border := Color veryLightGray. delay := Delay forMilliseconds: 50. w := World bounds corner x. h := (World bounds corner y) / 2. smw := w/100. smh := h/2.

m := BorderedMorph new position: 0@h. m height: smh; width: w; borderColor: border. m color: Color veryLightGray.

1 to: 100 do: [ :pos || sm | sm := BorderedMorph new height: smh ; width: smw ; borderColor: border; color: closedDoor; position: (smw*pos)@h. m addMorph: sm asElementNumber: pos].

m openInWorld. delay wait. subMorphList := m submorphs. "display every step" [1 to: 100 do: [ :step | step to: 100 by: step do: [ :pos | | subMorph | subMorph := subMorphList at: pos. subMorph color: subMorph color negated. delay wait]]] fork. </lang>

SETL

Unoptimized <lang setl>program hundred_doors;

const toggle := {['open', 'closed'], ['closed', 'open']};

doorStates := ['closed'] * 100;

(for interval in [1..100])

 doorStates := [if i mod interval = 0 then
                   toggle(prevState) else
                   prevState end:
                prevState = doorStates(i)];

end;

(for finalState = doorStates(i))

 print('door', i, 'is', finalState);

end;

end program;</lang> If 'open' weren't a reserved word, we could omit the single quotes around it.

Optimized Exploits the fact that squares are separated by successive odd numbers. Use array replication to insert the correct number of closed doors in between the open ones. <lang setl>program hundred_doors;

doorStates := (+/ [['closed'] * oddNum with 'open': oddNum in [1,3..17]]);

(for finalState = doorStates(i))

 print('door', i, 'is', finalState);

end;

end program;</lang>

Tcl

unoptimized

<lang tcl>package require Tcl 8.5 set n 100 set doors [concat - [lrepeat $n 0]] for {set step 1} {$step <= $n} {incr step} {

   for {set i $step} {$i <= $n} {incr i $step} {
       lset doors $i [expr { ! [lindex $doors $i]}]
   }

} for {set i 1} {$i <= $n} {incr i} {

   puts [format "door %d is %s" $i [expr {[lindex $doors $i] ? "open" : "closed"}]]

}</lang>

optimized

<lang tcl>package require Tcl 8.5 set doors [lrepeat [expr {$n + 1}] closed] for {set i 1} {$i <= sqrt($n)} {incr i} {

   lset doors [expr {$i ** 2}] open

} for {set i 1} {$i <= $n} {incr i} {

   puts [format "door %d is %s" $i [lindex $doors $i]]

}</lang>

graphical

Library: Tk

Inspired by the E solution, here's a visual representation <lang tcl>package require Tcl 8.5 package require Tk

array set door_status {}

  1. create the gui

set doors [list x] for {set i 0} {$i < 10} {incr i} {

   for {set j 0} {$j < 10} {incr j} {
       set k [expr {1 + $j + 10*$i}]
       lappend doors [radiobutton .d_$k -text $k -variable door_status($k) \
                        -indicatoron no -offrelief flat -width 3 -value open]
       grid [lindex $doors $k] -column $j -row $i
   }

}

  1. create the controls

button .start -command go -text Start label .i_label -text " door:" entry .i -textvariable i -width 4 label .step_label -text " step:" entry .step -textvariable step -width 4 grid .start - .i_label - .i - .step_label - .step - -row $i grid configure .start -sticky ew grid configure .i_label .step_label -sticky e grid configure .i .step -sticky w

proc go {} {

   global doors door_status i step
   # initialize the door_status (all closed)
   for {set d 1} {$d <= 100} {incr d} {
       set door_status($d) closed
   }
   
   # now, begin opening and closing
   for {set step 1} {$step <= 100} {incr step} {
       for {set i 1} {$i <= 100} {incr i} {
           if {$i % $step == 0} {
               [lindex $doors $i] [expr {$door_status($i) eq "open" ? "deselect" : "select"}]
               update
               after 50
           }
       }
   }

}</lang>

TI-89 BASIC

<lang ti89b>Define doors(fast) = Func

 Local doors,i,j
 seq(false,x,1,100) → doors
 If fast Then
   For i,1,10,1
     true → doors[i^2]
   EndFor
 Else
   For i,1,100,1
     For j,i,100,i
       not doors[j] → doors[j]
     EndFor
   EndFor
 EndIf
 Return doors

EndFunc</lang>

UNIX Shell

Works with: Bourne Again SHell

<lang bash>#! /bin/bash

declare -a doors for((i=1; i <= 100; i++)); do

   doors[$i]=0

done

for((i=1; i <= 100; i++)); do

   for((j=i; j <= 100; j += i)); do

echo $i $j doors[$j]=$(( doors[j] ^ 1 ))

   done

done

for((i=1; i <= 100; i++)); do

   if [[ ${doors[$i]} -eq 0 ]]; then

op="closed"

   else

op="open"

   fi
   echo $i $op

done</lang>

Ursala

The doors are represented as a list of 100 booleans initialized to false. The pass function takes a number and a door list to a door list with doors toggled at indices that are multiples of the number. The main program folds the pass function (to the right) over the list of pass numbers from 100 down to 1, numbers the result, and filters out the numbers of the open doors. <lang Ursala>#import std

  1. import nat

doors = 0!* iota 100

pass("n","d") = remainder\"n"?l(~&r,not ~&r)* num "d"

  1. cast %nL

main = ~&rFlS num pass=>doors nrange(100,1)</lang> optimized version: <lang Ursala>#import nat

  1. cast %nL

main = product*tiiXS iota10</lang> output:

<1,4,9,16,25,36,49,64,81>

VBScript

Works with: Windows Script Host version 5.7

Unoptimized <lang VBScript>Dim doorIsOpen(100), pass, currentDoor, text

For currentDoor = 0 To 99 doorIsOpen(currentDoor) = False Next

For pass = 0 To 99 For currentDoor = pass To 99 Step pass + 1 doorIsOpen(currentDoor) = Not doorIsOpen(currentDoor) Next Next

For currentDoor = 0 To 99 text = "Door #" & currentDoor + 1 & " is " If doorIsOpen(currentDoor) Then text = text & "open." Else text = text & "closed." End If WScript.Echo(text) Next</lang>


Vedit macro language

Unoptimized This implementation uses a free edit buffer as data array and for displaying the results.
A closed door is represented by a character '-' and an open door by character 'O'. <lang vedit>Buf_Switch(Buf_Free) Ins_Char('-', COUNT, 100) // All doors closed for (#1 = 1; #1 <= 100; #1++) {

   for (#2 = #1; #2 <= 100; #2 += #1) {
       Goto_Col(#2)
       Ins_Char((Cur_Char^0x62), OVERWRITE)   // Toggle between '-' and 'O'
   }

}</lang>

Optimized <lang vedit>Buf_Switch(Buf_Free) Ins_Char('-', COUNT, 100) for (#1=1; #1 <= 10; #1++) {

   Goto_Col(#1*#1)
   Ins_Char('O', OVERWRITE)

}</lang>

Output:

O--O----O------O--------O----------O------------O--------------O----------------O------------------O

Visual Basic .NET

Works with: Visual Basic .NET version 9.0+

unoptimized <lang vbnet>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</lang> optimized <lang vbnet>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</lang>