100 doors

From Rosetta Code
Jump to: navigation, search
Task
100 doors
You are encouraged to solve this task according to the task description, using any language you may know.

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.

Contents

[edit] 4DOS Batch

 
@echo off
set doors=%@repeat[C,100]
do step = 1 to 100
do door = %step to 100 by %step
set doors=%@left[%@eval[%door-1],%doors]%@if[%@instr[%@eval[%door-1],1,%doors]==C,O,C]%@right[%@eval[100-%door],%doors]
enddo
enddo
 

The SET line consists of three functions:

 
%@left[n,string] ^: Return n leftmost chars in string
%@right[n,string] ^: Return n rightmost chars in string
%@if[condition,true-val,false-val] ^: Evaluate condition; return true-val if true, false-val if false
 

Here @IF is used to toggle between C and O.

[edit] 6502 Assembly

Works with: [www.6502asm.com] version beta

unoptimized Based on BASIC QB64 unoptimized version

; 100 DOORS in  6502 assembly language for: http://www.6502asm.com/beta/index.html
; Written for the original MOS Technology, Inc. NMOS version of the 6502, but should work with any version.
; Based on BASIC QB64 unoptimized version: http://rosettacode.org/wiki/100_doors#BASIC
;
; Notes:
; Doors array[1..100] is at $0201..$0264. On the specified emulator, this is in video memory, so tbe results will
; be directly shown as pixels in the display.
; $0200 (door 0) is cleared for display purposes but is not involved in the open/close loops.
; Y register holds Stride
; X register holds Index
; Zero Page address $01 used to add Stride to Index (via A) because there's no add-to-X or add-Y-to-A instruction.
 
 ; First, zero door array
LDA #00
LDX #100
Z_LOOP:
STA 200,X
DEX
BNE Z_LOOP
STA 200,X
 
 ; Now do doors repeated open/close
LDY #01  ; Initial value of Stride
S_LOOP:
CPY #101
BCS S_DONE
TYA  ; Initial value of Index
I_LOOP:
CMP #101
BCS I_DONE
TAX  ; Use as Door array index
INC $200,X  ; Toggle bit 0 to reverse state of door
STY 01  ; Add stride (Y) to index (X, via A)
ADC 01
BCC I_LOOP
I_DONE:
INY
BNE S_LOOP
S_DONE:
 
 ; Finally, format array values for output: 0 for closed, 1 for open
LDX #100
C_LOOP:
LDA $200,X
AND #$01
STA $200,X
DEX
BNE C_LOOP

48. bytes of code; the specified emulator does not report cycles.


Works with: [6502asm.com] version 1.2

optimized Largely inspired by the optimized C implementation - makes use of the fact that finally only the doors whose numbers are squares of integers are open, as well as the fact that

n^2 = 1 + 3 + 5 + \ldots + (2n-1).
  ;assumes memory at $02xx is initially set to 0 and stack pointer is initialized
 ;the 1 to 100 door byte array will be at $0200-$0263 (decimal 512 to 611)
 ;Zero-page location $01 will hold delta
 ;At end, closed doors = $00, open doors = $01
 
start: ldx #0  ;initialize index - first door will be at $200 + $0
stx $1
inc $1  ;start out with a delta of 1 (0+1=1)
openloop: inc $200,X  ;open X'th door
inc $1  ;add 2 to delta
inc $1
txa  ;add delta to X by transferring X to A, adding delta to A, then transferring back to X
clc  ; clear carry before adding (6502 has no add-without-carry instruction)
adc $1
tax
cpx #$64  ;check to see if we're at or past the 100th door (at $200 + $63)
bmi openloop  ;jump back to openloop if less than 100

22. bytes of code; the specified emulator does not report cycles.

[edit] 68000 Assembly

Works with: [EASy68K v5.13.00]

Some of the macro code is derived from the examples included with EASy68K.

*-----------------------------------------------------------
* Title  : 100Doors.X68
* Written by : G. A. Tippery
* Date  : 2014-01-17
* Description: Solves "100 Doors" problem, see: http://rosettacode.org/wiki/100_doors
* Notes  : Translated from C "Unoptimized" version, http://rosettacode.org/wiki/100_doors#unoptimized
*  : No optimizations done relative to C version; "for("-equivalent loops could be optimized.
*-----------------------------------------------------------
 
*
* System-specific general console I/O macros (Sim68K, in this case)
*
PUTS MACRO
** Print a null-terminated string w/o CRLF **
** Usage: PUTS stringaddress
** Returns with D0, A1 modified
MOVEQ #14,D0  ; task number 14 (display null string)
LEA \1,A1  ; address of string
TRAP #15  ; display it
ENDM
*
PRINTN MACRO
** Print decimal integer from number in register
** Usage: PRINTN register
** Returns with D0,D1 modified
IFNC '\1','D1'  ;if some register other than D1
MOVE.L \1,D1  ;put number to display in D1
ENDC
MOVE.B #3,D0
TRAP #15  ;display number in D1
*
* Generic constants
*
CR EQU 13  ;ASCII Carriage Return
LF EQU 10  ;ASCII Line Feed
 
*
* Definitions specific to this program
*
* Register usage:
* D3 == pass (index)
* D4 == door (index)
* A2 == Doors array pointer
*
SIZE EQU 100  ;Define a symbolic constant for # of doors
 
ORG $1000  ;Specify load address for program -- actual address system-specific
START:  ; Execution starts here
LEA Doors,A2  ; make A2 point to Doors byte array
MOVEQ #0,D3
PassLoop:
CMP #SIZE,D3
BCC ExitPassLoop  ; Branch on Carry Clear - being used as Branch on Higher or Equal
MOVE D3,D4
DoorLoop:
CMP #SIZE,D4
BCC ExitDoorLoop
NOT.B 0(A2,D4)
ADD D3,D4
ADDQ #1,D4
BRA DoorLoop
ExitDoorLoop:
ADDQ #1,D3
BRA PassLoop
ExitPassLoop:
 
* $28 = 40. bytes of code to this point. 32626 cycles so far.
* At this point, the result exists as the 100 bytes starting at address Doors.
* To get output, we must use methods specific to the particular hardware, OS, or
* emulator system that the code is running on. I use macros to "hide" some of the
* system-specific details; equivalent macros would be written for another system.
 
MOVEQ #0,D4
PrintLoop:
CMP #SIZE,D4
BCC ExitPrintLoop
PUTS DoorMsg1
MOVE D4,D1
ADDQ #1,D1  ; Convert index to 1-based instead of 0-based
PRINTN D1
PUTS DoorMsg2
TST.B 0(A2,D4)  ; Is this door open (!= 0)?
BNE ItsOpen
PUTS DoorMsgC
BRA Next
ItsOpen:
PUTS DoorMsgO
Next:
ADDQ #1,D4
BRA PrintLoop
ExitPrintLoop:
 
* What to do at end of program is also system-specific
SIMHALT  ;Halt simulator
*
* $78 = 120. bytes of code to this point, but this will depend on how the I/O macros are actually written.
* Cycle count is nearly meaningless, as the I/O hardware and routines will dominate the timing.
 
*
* Data memory usage
*
ORG $2000
Doors DCB.B SIZE,0  ;Reserve 100 bytes, prefilled with zeros
 
DoorMsg1 DC.B 'Door ',0
DoorMsg2 DC.B ' is ',0
DoorMsgC DC.B 'closed',CR,LF,0
DoorMsgO DC.B 'open',CR,LF,0
 
END START  ;last line of source
 
 

[edit] 8086 Assembly

See 100 doors/8086 Assembly

[edit] ABAP

unoptimized

form open_doors_unopt.
data: lv_door type i,
lv_count type i value 1.
data: lt_doors type standard table of c initial size 100.
field-symbols: <wa_door> type c.
do 100 times.
append initial line to lt_doors assigning <wa_door>.
<wa_door> = 'X'.
enddo.
 
while lv_count < 100.
lv_count = lv_count + 1.
lv_door = lv_count.
while lv_door < 100.
read table lt_doors index lv_door assigning <wa_door>.
if <wa_door> = ' '.
<wa_door> = 'X'.
else.
<wa_door> = ' '.
endif.
add lv_count to lv_door.
endwhile.
endwhile.
 
loop at lt_doors assigning <wa_door>.
if <wa_door> = 'X'.
write : / 'Door', (4) sy-tabix right-justified, 'is open' no-gap.
endif.
endloop.
endform.

optimized

Using \sum_{i=1}^n (2i-1) = n^2

form open_doors_opt.
data: lv_square type i value 1,
lv_inc type i value 3.
data: lt_doors type standard table of c initial size 100.
field-symbols: <wa_door> type c.
do 100 times.
append initial line to lt_doors assigning <wa_door>.
if sy-index = lv_square.
<wa_door> = 'X'.
add: lv_inc to lv_square, 2 to lv_inc.
write : / 'Door', (4) sy-index right-justified, 'is open' no-gap.
endif.
enddo.
endform.

[edit] ACL2

(defun rep (n x)
(if (zp n)
nil
(cons x
(rep (- n 1) x))))
 
(defun toggle-every-r (n i bs)
(if (endp bs)
nil
(cons (if (zp i)
(not (first bs))
(first bs))
(toggle-every-r n (mod (1- i) n) (rest bs)))))
 
(defun toggle-every (n bs)
(toggle-every-r n (1- n) bs))
 
(defun 100-doors (i doors)
(if (zp i)
doors
(100-doors (1- i) (toggle-every i doors))))

[edit] ActionScript

Works with: ActionScript version 3.0

unoptimized

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);
}
}
}

[edit] 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;

[edit] 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"))
 
}
 
 

[edit] 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)

[edit] 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

[edit] APL

Works with: Dyalog APL

unoptimized

out←doors num
⍝ Simulates the 100 doors problem for any number of doors
⍝ Returns a boolean vector with 1 being open
 
out←⍳num ⍝ num steps
out←⍳¨out ⍝ Count out the spacing for each step
out←1=out ⍝ Make that into a boolean vector
out←⌽¨out ⍝ Flip each vector around
out←(num∘⍴)¨out ⍝ Copy each out to the right size
out←≠/out ⍝ XOR each vector, toggling each marked door
out←⊃out ⍝ Disclose the results to get a vector

Sample Output:

 10 10⍴doors 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 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1  

optimized

out←doorsOptimized num;marks
⍝ Returns a boolean vector of the doors that would be left open
 
marks←⌊num*0.5 ⍝ Take the square root of the size, floored
marks←(⍳marks)*2 ⍝ Get each door to be opened
out←num⍴0 ⍝ Make a vector of 0s
out[marks]←1 ⍝ Set the marked doors to 1

Sample Output:

 10 10⍴doorsOptimized 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 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1  

Alternate 1-line version Note that ⎕IO = 1

2|+/[1]0=D∘.|D←⍳100

The idea is that the n:th door will be flipped the same number of times as there are divisors for n. So first we make D all ints 1..100 (D←⍳100).
The next step is to find the remainders of every such int when divided by every other (D∘.|D).
This results in a 100×100 matrix which we turn into a binary one by testing if the values are equal to zero i.e. divisors.
Next: sum along axis 1, i.e. the columns. This tells us the number of divisors. Finally calculate the remainder of these when divided by 2, i.e. find which n have an odd number of divisors, i.e. will be flipped an odd number of times and thus end up open.

[edit] AppleScript

set is_open to {}
repeat 100 times
set end of is_open to false
end
repeat with pass from 1 to 100
repeat with door from pass to 100 by pass
set item door of is_open to not item door of is_open
end
end
set open_doors to {}
repeat with door from 1 to 100
if item door of is_open then
set end of open_doors to door
end
end
set text item delimiters to ", "
display dialog "Open doors: " & open_doors

[edit] Arbre

 
openshut(n):
for x in [1..n]
x%n==0
 
pass(n):
if n==100
openshut(n)
else
openshut(n) xor pass(n+1)
 
100doors():
pass(1) -> io
 

[edit] 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]"

[edit] AutoHotkey

[edit] Standard Approach

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

[edit] Alternative Approach

Making use of the identity:

\sum_{i=1}^n (2i-1) = n^2

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)

[edit] Optimized

While (Door := A_Index ** 2) <= 100
Result .= "Door " Door " is open`n"
MsgBox, %Result%

[edit] AutoIt

 
#include <array.au3>
$doors = 100
 
;door array, 0 = closed, 1 = open
Local $door[$doors +1]
 
For $ii = 1 To $doors
For $i = $ii To $doors Step $ii
$door[$i] = Not $door[$i]
next
Next
 
;display to screen
For $i = 1 To $doors
ConsoleWrite (Number($door[$i])& " ")
If Mod($i,10) = 0 Then ConsoleWrite(@CRLF)
Next
 

[edit] Axiom

Unoptimized:
(open,closed,change,open?) := (true,false,not,test);
doors := bits(100,closed);
for i in 1..#doors repeat
for j in i..#doors by i repeat
doors.j := change doors.j
[i for i in 1..#doors | open? doors.i]
 
Optimized:
[i for i in 1..100 | perfectSquare? i] -- or
[i^2 for i in 1..sqrt(100)::Integer]

[edit] AWK

unoptimized

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"
}
}

optimized

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"
}
}

[edit] BASIC

Works with: QBASIC, QB64

unoptimized

REM "100 Doors" program FOR QB64 BASIC (http://www.qb64.net/), a QuickBASIC-like compiler.
REM Author: G. A. Tippery
REM Date: 12-Feb-2014
REM
REM Unoptimized (naive) version, per specifications at http://rosettacode.org/wiki/100_doors
 
DEFINT A-Z
CONST N = 100
DIM door(N)
 
FOR stride = 1 TO N
FOR index = stride TO N STEP stride
LET door(index) = NOT (door(index))
NEXT index
NEXT stride
 
PRINT "Open doors:"
FOR index = 1 TO N
IF door(index) THEN PRINT index
NEXT index
 
END
Works with: QuickBasic version 4.5

unoptimized

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

optimized

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

optimized

 
'lrcvs 04.11.12
CLS
x = 1 : y = 3 : z = 0
PRINT x + " Open"
DO
z = x + y
PRINT z + " Open"
x = z : y = y + 2
UNTIL z >= 100
END
 

[edit] BASIC256

# 100 doors problem
dim d(100)
 
# simple solution
print "simple solution"
gosub initialize
for t = 1 to 100
for j = t to 100 step t
d[j-1] = not d[j-1]
next j
next t
gosub showopen
 
# more optimized solution
print "more optimized solution"
gosub initialize
for t = 1 to 10
d[t^2-1] = true
next t
gosub showopen
end
 
initialize:
for t = 1 to d[?]
d[t-1] = false # closed
next t
return
 
showopen:
for t = 1 to d[?]
print d[t-1]+ " ";
if t%10 = 0 then print
next t
return

[edit] Batch File

unoptimized

 
@echo off
setlocal enableDelayedExpansion
:: 0 = closed
:: 1 = open
:: SET /A treats undefined variable as 0
:: Negation operator ! must be escaped because delayed expansion is enabled
for /l %%p in (1 1 100) do for /l %%d in (%%p %%p 100) do set /a "door%%d=^!door%%d"
for /l %%d in (1 1 100) do if !door%%d!==1 (
echo door %%d is open
) else echo door %%d is closed
 

optimized

 
@echo off
setlocal enableDelayedExpansion
set /a square=1, incr=3
for /l %%d in (1 1 100) do (
if %%d neq !square! (echo door %%d is closed) else (
echo door %%d is open
set /a square+=incr, incr+=2
)
)
 

[edit] BBC BASIC

      DIM doors%(100)
 
FOR pass% = 1 TO 100
FOR door% = pass% TO 100 STEP pass%
doors%(door%) = NOT doors%(door%)
NEXT door%
NEXT pass%
 
FOR door% = 1 TO 100
IF doors%(door%) PRINT "Door " ; door% " is open"
NEXT door%

[edit] bc

/* 0 means door is closed, 1 means door is open */
for (i = 0; i < 100; i++) {
for (j = i; j < 100; j += (i + 1)) {
d[j] = 1 - d[j] /* Toggle door */
}
}
 
"Open doors:
"
for (i = 0; i < 100; i++) {
if (d[i] == 1) (i + 1)
}

[edit] Befunge

Works with: CCBI version 2.1
108p0>:18p;;>:9g!18g9p08g]
*`!0\|+relet|-1`*aap81::+]
;::+1<r]!g9;>$08g1+:08paa[
*`#@_^._aa

[edit] BlitzMax

Works with: BlitzMax version 1.37

optimized

Graphics 640,480
i=1
While ((i*i)<=100)
a$=i*i
DrawText a$,10,20*i
Print i*i
i=i+1
Wend
Flip
WaitKey

[edit] Bracmat

Bracmat is not really at home in tasks that involve addressing things by index number. Here are four solutions that each do the task, but none should win a price for cleanliness.

Solution 1. Use an indexable array. Local variables are stored in stacks. Each stack corresponds to one variable name and vice versa. Stacks can also be used as arrays, but because of how local variables are implemented, arrays cannot be declared as local variables.

( 100doors-tbl
= door step
. tbl$(doors.101) { Create an array. Indexing is 0-based. Add one extra for addressing element nr. 100 }
& 0:?step
& whl
' ( 1+!step:~>100:?step { ~> means 'not greater than', i.e. 'less than or equal' }
& 0:?door
& whl
' ( !step+!door:~>100:?door
& 1+-1*!(!door$doors):?doors { <number>$<variable> sets the current index, which stays the same until explicitly changed. }
)
)
& 0:?door
& whl
' ( 1+!door:~>100:?door
& out
$ ( door
 !door
is
( !(!door$doors):1&open
| closed
)
)
)
& tbl$(doors.0) { clean up the array }
)

Solution 2. Use one variable for each door. In Bracmat, a variable name can be any non-empty string, even a number, so we use the numbers 1 .. 100 as variable names, but also as door numbers. When used as variable an extra level of indirection is needed. See the occurrences of ?! and !! in the following code.

( 100doors-var
= step door
. 0:?door
& whl
' ( 1+!door:~>100:?door
& closed:?!door { this creates a variable and assigns a value 'closed' to it }
)
& 0:?step
& whl
' ( 1+!step:~>100:?step
& 0:?door
& whl
' ( !step+!door:~>100:?door
& ( !!door:closed&open
| closed
)
 : ?!door
)
)
& 0:?door
& whl
' ( 1+!door:~>100:?door
& out$(door !door is !!door)
)
& 0:?door
& whl
' ( 1+!door:~>100:?door
& tbl$(!door.0) { cleanup the variable }
)
)

Solution 3. Use a list and a dedicated positioning pattern to address the right door in the list. Create a new list by concatenating the skipped elements with the toggled elements. This solution is computationally unfavourable because of the many concatenations.

( 100doors-list
= doors door doorIndex step
.  :?doors
& 0:?door
& whl
' ( 1+!door:~>100:?door
& closed !doors:?doors
)
& 0:?skip
& whl
' ( :?ndoors
& whl
' ( !doors:?skipped [!skip %?door ?doors { the [<number> pattern only succeeds when the scanning cursor is at position <number> }
&  !ndoors
 !skipped
( !door:open&closed
| open
)
 : ?ndoors
)
& !ndoors !doors:?doors
& 1+!skip:<100:?skip
)
& out$!doors
)

Solution 4. Use a list of objects. Each object can be changed without the need to re-create the whole list.

( 100doors-obj
= doors door doorIndex step
.  :?doors
& 0:?door
& whl
' ( 1+!door:~>100:?door
& new$(=closed) !doors:?doors
)
& 0:?skip
& whl
' ( !doors:?tododoors
& whl
' ( !tododoors:? [!skip %?door ?tododoors
& ( !(door.):open&closed
| open
)
 : ?(door.)
)
& 1+!skip:<100:?skip
)
& out$!doors
)

These four functions are called in the following way:

100doors-tbl$
& 100doors-var$
& 100doors-list$
& 100doors-obj$;

[edit] Burlesque

Version using square numbers:

 
blsq ) 10ro2?^
{1 4 9 16 25 36 49 64 81 100}
 

[edit] C

[edit] unoptimized

Uses: C Runtime (Components:printf,)
#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;
}

Using defensive programming, pointers, sentinel values and some other standard programming practices,

Uses: C Runtime (Components:printf,)
#include <stdio.h>
 
#define NUM_DOORS 100
 
int main(int argc, char *argv[])
{
int is_open[NUM_DOORS] = { 0 } ;
int * doorptr, * doorlimit = is_open + NUM_DOORS ;
int pass ;
 
/* do the N passes, go backwards because the order is not important */
for ( pass= NUM_DOORS ; ( pass ) ; -- pass ) {
for ( doorptr= is_open + ( pass-1 ); ( doorptr < doorlimit ) ; doorptr += pass ) {
( * doorptr ) ^= 1 ;
}
}
 
/* output results */
for ( doorptr= is_open ; ( doorptr != doorlimit ) ; ++ doorptr ) {
printf("door #%ld is %s\n", ( doorptr - is_open ) + 1, ( * doorptr ) ? "open" : "closed" ) ;
}
}

[edit] 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 n^2 = 1 + 3 + 5 + \ldots + (2n-1).

Uses: C Runtime (Components:printf,)
#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;
}

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

#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;
}
Or really optimize it -- square of an integer is, well, computable:
#include <stdio.h>
 
int main()
{
int i;
for (i = 1; i * i <= 100; i++)
printf("door %d open\n", i * i);
 
return 0;
}

[edit] C++

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

unoptimized

#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;
}

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 (n+1)^2 = 1 + 3 + 5 + \ldots + (2n+1).

#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;
}

The only calculation that's really needed:

#include <iostream> //compiled with "Dev-C++" , from RaptorOne
 
int main()
{
for(int i=1; i*i<=100; i++)
std::cout<<"Door "<<i*i<<" is open!"<<std::endl;
}

[edit] C#

Unoptimized

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);
}
}

Optimized

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");
}
}
}

Optimized for brevity

using System;
class Program
{
static void Main()
{
double n;
for (int t = 1; t <= 100; ++t)
Console.WriteLine(t + ": " + (((n = Math.Sqrt(t)) == (int)n) ? "Open" : "Closed"));
}
}

Unoptimized with modulus '%' operator

 using System;
class Program
{
static void Main(string[] args)
{
bool[] Doors = new bool[101];
 
 
//Close all doors to start
for (int g=1;g<101;g++) Doors[g] = false;
 
for (int i = 1; i < 101; i++)//number of passes
{
for (int d = 1; d < 101; d++)//door number
{
if ((d % i) == 0)
{
if (Doors[d]) Doors[d] = false;
else Doors[d] = true;
}
 
}
}
 
Console.WriteLine("Passes Completed!!! Here are the results: \r\n");
for (int p = 1; p < 101; p++)
{
if (Doors[p])
{
string doorStatus = String.Format("Door #{0} is \'OPENED\'.", p.ToString());
Console.WriteLine(doorStatus);
}
else
{
string doorStatus = String.Format("Door #{0} is \'CLOSED\'.", p.ToString());
Console.WriteLine(doorStatus);
}
 
}
}
}
 

Alternate optimisation (This version demonstrates a different thought pattern during development, where operation and presentation are separated. It could easily be refactored so that the operations to determine which doors are opened and to display the list of doors would be in separate methods, at which point it would become simple to extract them to separate classes and employ a DI pattern to switch the algorithm or display mechanism being used. It also keeps the calculation clear and concise.)

 
class Program
{
static void Main(string[] args)
{
bool[] doorStates = new bool[100];
int n = 0;
int d;
while ((d = (++n * n)) <= 100)
doorStates[d - 1] = true;
for (int i = 0; i < doorStates.Length; i++)
Console.WriteLine("Door {0}: {1}", i + 1, doorStates[i] ? "Open" : "Closed");
Console.ReadKey(true);
}
}
 

[edit] C1R

100_doors

[edit] CLIPS

Unoptimized

(deffacts initial-state
(door-count 100)
)
 
(deffunction toggle
(?state)
(switch ?state
(case "open" then "closed")
(case "closed" then "open")
)
)
 
(defrule create-doors-and-visits
(door-count ?count)
=>
(loop-for-count (?num 1 ?count) do
(assert (door ?num "closed"))
(assert (visit-from ?num ?num))
)
(assert (doors initialized))
)
 
(defrule visit
(door-count ?max)
 ?visit <- (visit-from ?num ?step)
 ?door <- (door ?num ?state)
=>
(retract ?visit)
(retract ?door)
(assert (door ?num (toggle ?state)))
(if
(<= (+ ?num ?step) ?max)
then
(assert (visit-from (+ ?num ?step) ?step))
)
)
 
(defrule start-printing
(doors initialized)
(not (visit-from ? ?))
=>
(printout t "These doors are open:" crlf)
(assert (print-from 1))
)
 
(defrule print-door
(door-count ?max)
 ?pf <- (print-from ?num)
(door ?num ?state)
=>
(retract ?pf)
(if
(= 0 (str-compare "open" ?state))
then
(printout t ?num " ")
)
(if
(< ?num ?max)
then
(assert (print-from (+ ?num 1)))
else
(printout t crlf "All other doors are closed." crlf)
)
)

Optimized

(deffacts initial-state
(door-count 100)
)
 
(deffunction is-square
(?num)
(= (sqrt ?num) (integer (sqrt ?num)))
)
 
(defrule check-doors
(door-count ?count)
=>
(printout t "These doors are open:" crlf)
(loop-for-count (?num 1 ?count) do
(if (is-square ?num) then
(printout t ?num " ")
)
)
(printout t crlf "All other doors are closed." crlf)
)

[edit] Clojure

Unoptimized / mutable array

(defn doors []
(let [doors (into-array (repeat 100 false))]
(doseq [pass (range 1 101)
i (range (dec pass) 100 pass) ]
(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)))))

Unoptimized / functional

(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) ]
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)))))

Optimized / functional

(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)))))

[edit] COBOL

       IDENTIFICATION DIVISION.
PROGRAM-ID. 100Doors.
 
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Current-n PIC 9(3).
01 StepSize PIC 9(3).
01 DoorTable.
02 Doors PIC 9(1) OCCURS 100 TIMES.
88 ClosedDoor VALUE ZERO.
01 Idx PIC 9(3).
 
PROCEDURE DIVISION.
Begin.
INITIALIZE DoorTable
PERFORM VARYING StepSize FROM 1 BY 1 UNTIL StepSize > 100
PERFORM VARYING Current-n FROM StepSize BY StepSize
UNTIL Current-n > 100
SUBTRACT Doors (Current-n) FROM 1 GIVING Doors (Current-n)
END-PERFORM
END-PERFORM
 
PERFORM VARYING Idx FROM 1 BY 1
UNTIL Idx > 100
IF ClosedDoor (Idx)
DISPLAY Idx " is closed."
ELSE
DISPLAY Idx " is open."
END-IF
END-PERFORM
 
STOP RUN
.

[edit] Coco

We use the naive algorithm.

doors = [false] * 100
 
for pass til doors.length
for i from pass til doors.length by pass + 1
 ! = doors[i]
 
for i til doors.length
console.log 'Door %d is %s.', i + 1, if doors[i] then 'open' else 'closed'

[edit] CoffeeScript

unoptimized:

doors = []
 
for pass in [1..100]
for i in [pass..100] by pass
doors[i] = !doors[i]
 
console.log "Doors #{index for index, open of doors when open} are open"
 
# matrix output
console.log doors.map (open) -> +open
 

optimized:

isInteger = (i) -> Math.floor(i) == i
 
console.log door for door in [1..100] when isInteger Math.sqrt door

ultra-optimized:

console.log Math.pow(i,2) for i in [1..10]

[edit] ColdFusion

Basic Solution: Returns List of 100 values: 1=open 0=closed

 
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;
}
 

Squares of Integers Solution: Returns List of 100 values: 1=open 0=closed

 
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;
}
 

Display only

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

[edit] Common Lisp

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

(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 (eql (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))))

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

(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)))))

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)

(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) "_")))

Optimized (2) This version displays a much more functional solution through the use of MAPCAR (note however that this is imperative as it does variable mutation)

(let  ((i 0))
(mapcar (lambda (x)
(if (zerop (mod (sqrt (incf i)) 1))
"_" "#"))
(make-list 100)))

[edit] Component Pascal

BlackBox Component Builder

 
MODULE Doors100;
IMPORT StdLog;
 
PROCEDURE Do*;
VAR
i,j: INTEGER;
closed: ARRAY 101 OF BOOLEAN;
BEGIN
(* initilization of close to true *)
FOR i := 0 TO LEN(closed) - 1 DO closed[i] := TRUE END;
(* process *)
FOR i := 1 TO LEN(closed) DO;
j := 1;
WHILE j < LEN(closed) DO
IF j MOD i = 0 THEN closed[j] := ~closed[j] END;INC(j)
END
END;
(* print results *)
i := 1;
WHILE i < LEN(closed) DO
IF (i - 1) MOD 10 = 0 THEN StdLog.Ln END;
IF closed[i] THEN StdLog.String("C ") ELSE StdLog.String("O ") END;
INC(i)
END;
END Do;
END Doors100.
 
 

Execute: ^Q Doors100.Do
Output:

O C C O C C C C O C 
C C C C C O C C C C 
C C C C O C C C C C 
C C C C C O C C C C 
C C C C C C C C O C 
C C C C C C C C C C 
C C C O C C C C C C 
C C C C C C C C C C 
O C C C C C C C C C 
C C C C C C C C C O 

[edit] Coq

Basic solution:

Require Import List.
 
Fixpoint rep {A} (a : A) n :=
match n with
| O => nil
| S n' => a::(rep a n')
end.
 
Fixpoint flip (l : list bool) (n k : nat) : list bool :=
match l with
| nil => nil
| cons h t => match k with
| O => (negb h) :: (flip t n n)
| S k' => h :: (flip t n k')
end
end.
 
Definition flipeach l n := flip l n n.
 
Fixpoint flipwhile l n :=
match n with
| O => flipeach l 0
| S n' => flipwhile (flipeach l (S n')) n'
end.
 
Definition prison cells := flipwhile (rep false (S cells)) cells.

Optimized version ((n+1)^2 = n^2 + 2n + 1):

Require Import List.
 
Fixpoint prisoo' nd n k accu :=
match nd with
| O => rev accu
| S nd' => let ra := match k with
| O => (true, S n, (n + n))
| S k' => (false, n, k')
end in
prisoo' nd' (snd (fst ra)) (snd ra) ((fst (fst ra))::accu)
end.
 
Definition prisoo n := prisoo' (S n) 1 0 nil.

Unit test:

Goal prison 100 = prisoo 100. compute. reflexivity. Qed.

Full proof at github:

Goal forall n, prison n = prisoo n. Abort.

[edit] D

import std.stdio, std.algorithm, std.range;
 
enum DoorState : bool { closed, open }
alias Doors = DoorState[];
 
Doors flipUnoptimized(Doors doors) pure nothrow {
doors[] = DoorState.closed;
 
foreach (immutable 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) pure nothrow {
doors[] = DoorState.closed;
for (int i = 1; i ^^ 2 <= doors.length; i++)
doors[i ^^ 2 - 1] = DoorState.open;
return doors;
}
 
void main() {
auto doors = new Doors(100);
 
foreach (const open; [doors.dup.flipUnoptimized,
doors.dup.flipOptimized])
iota(1, open.length + 1).filter!(i => open[i - 1]).writeln;
}
Output:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Unoptimized. Demonstrates very basic language syntax/features. Program output allows to see what the code is doing:

 
import std.stdio;
 
void printAllDoors(bool[] doors)
{
// Prints the state of all the doors
foreach(i, door; doors)
{
writeln("#: ", i + 1, (door) ? " open" : " closed");
}
}
void main()
{
bool[100] doors = false; //Create 100 closed doors
for(int a = 0; a < 100; ++a) {
writefln("Pass #%s; visiting every %s door.", a + 1, a + 1); // Optional
for(int i = a; i < 100; i += (a + 1)) {
writefln("Visited door %s", i + 1); //Optional
doors[i] = !doors[i];
}
writeln(); // Optional
}
printAllDoors(doors); // Prints the state of each door
}
 

[edit] Dart

unoptimized

main() {
for (var k = 1, x = new List(101); k <= 100; k++) {
for (int i = k; i <= 100; i += k)
x[i] = !x[i];
if (x[k]) print("$k open");
}
}

optimized version (including generating squares without multiplication)

main() {
for(int i=1,s=3;i<=100;i+=s,s+=2)
print("door $i is open");
}

[edit] DCL

Adapted from optimized Batch example

 
$! doors.com
$! Excecute by running @doors at prompt.
$ square = 1
$ incr = 3
$ count2 = 0
$ d = 1
$ LOOP2:
$ count2 = count2 + 1
$ IF (d .NE. square)
$ THEN WRITE SYS$OUTPUT "door ''d' is closed"
$ ELSE WRITE SYS$OUTPUT "door ''d' is open"
$ square = incr + square
$ incr = incr + 2
$ ENDIF
$ d = d + 1
$ IF (count2 .LT. 100) THEN GOTO LOOP2
 

[edit] Delphi

See Pascal

[edit] Déjà Vu

local :open-doors [ rep 101 false ]
 
for i range 1 100:
local :j i
while <= j 100:
set-to open-doors j not open-doors! j
set :j + j i
 
!print\ "Open doors: "
for i range 1 100:
if open-doors! i:
!print\( to-str i " " )
Output:
Open doors: 1 4 9 16 25 36 49 64 81 100 

[edit] DWScript

Unoptimized

var doors : array [1..100] of Boolean;
var i, j : Integer;
 
for i := 1 to 100 do
for j := i to 100 do
if (j mod i) = 0 then
doors[j] := not doors[j];
 
for i := 1 to 100 do
if doors[i] then
PrintLn('Door '+IntToStr(i)+' is open');

[edit] Dylan

Unoptimized

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

[edit] E

Graphical

Works with: E-on-Java

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

#!/usr/bin/env rune
 
var toggles := []
var gets := []
 
# 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)
}
 
# Set up termination condition
def done
frame.addWindowListener(def _ {
to windowClosing(event) {
bind done := true
}
match _ {}
})
 
# 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)

[edit] ECL

optimized version

 
Doors := RECORD
UNSIGNED1 DoorNumber;
STRING6 State;
END;
 
AllDoors := DATASET([{0,0}],Doors);
 
Doors OpenThem(AllDoors L,INTEGER Cnt) := TRANSFORM
SELF.DoorNumber := Cnt;
SELF.State  := IF((CNT * 10) % (SQRT(CNT)*10)<>0,'Closed','Opened');
END;
 
OpenDoors := NORMALIZE(AllDoors,100,OpenThem(LEFT,COUNTER));
 
OpenDoors;
 

unoptimized version - demonstrating LOOP

 
Doors := RECORD
UNSIGNED1 DoorNumber;
STRING6 State;
END;
 
AllDoors := DATASET([{0,'0'}],Doors);
 
//first build the 100 doors
 
Doors OpenThem(AllDoors L,INTEGER Cnt) := TRANSFORM
SELF.DoorNumber := Cnt;
SELF.State  := 'Closed';
END;
 
ClosedDoors := NORMALIZE(AllDoors,100,OpenThem(LEFT,COUNTER));
 
//now iterate through them and use door logic
 
loopBody(DATASET(Doors) ds, UNSIGNED4 c) :=
PROJECT(ds, //ds=original input
TRANSFORM(Doors,
SELF.State := CASE((COUNTER % c) * 100,
0 => IF(LEFT.STATE = 'Opened','Closed','Opened')
,LEFT.STATE);
SELF.DoorNumber := COUNTER; //PROJECT COUNTER
));
 
g1 := LOOP(ClosedDoors,100,loopBody(ROWS(LEFT),COUNTER));
 
OUTPUT(g1);
 
 

unoptimized version - using ITERATE This is a bit more efficient than the LOOP version

 
DoorSet := DATASET(100,TRANSFORM({UNSIGNED1 DoorState},SELF.DoorState := 1));
SetDoors := SET(DoorSet,DoorState);
 
Doors := RECORD
UNSIGNED1 Pass;
SET OF UNSIGNED1 DoorSet;
END;
 
StartDoors := DATASET(100,TRANSFORM(Doors,SELF.Pass := COUNTER,SELF.DoorSet := SetDoors));
 
Doors XF(Doors L, Doors R) := TRANSFORM
ds := DATASET(L.DoorSet,{UNSIGNED1 DoorState});
NextDoorSet := PROJECT(ds,
TRANSFORM({UNSIGNED1 DoorState},
SELF.DoorState := CASE((COUNTER % R.Pass) * 100,
0 => IF(LEFT.DoorState = 1,0,1),
LEFT.DoorState)));
SELF.DoorSet := IF(L.Pass=0,R.DoorSet,SET(NextDoorSet,DoorState));
SELF.Pass := R.Pass
END;
 
Res := DATASET(ITERATE(StartDoors,XF(LEFT,RIGHT))[100].DoorSet,{UNSIGNED1 DoorState});
PROJECT(Res,TRANSFORM({STRING20 txt},SELF.Txt := 'Door ' + COUNTER + ' is ' + IF(LEFT.DoorState=1,'Open','Closed')));
 

[edit] Eero

 
#import <Foundation/Foundation.h>
 
int main()
square := 1, increment = 3
 
for int door in 1 .. 100
printf("door #%d", door)
 
if door == square
puts(" is open.")
square += increment
increment += 2
else
puts(" is closed.")
 
return 0
 

[edit] EGL

 
program OneHundredDoors
 
function main()
 
doors boolean[] = new boolean[100];
n int = 100;
 
for (i int from 1 to n)
for (j int from i to n by i)
doors[j] = !doors[j];
end
end
 
for (i int from 1 to n)
if (doors[i])
SysLib.writeStdout( "Door " + i + " is open" );
end
end
 
end
 
end
 

[edit] Eiffel

This is my first RosettaCode submission, as well as a foray into Eiffel for myself. I've tried to adhere to the description of the problem statement, as well as showcase a few Eiffelisms shown in the documentation.

file: application.e

note
description: "100 Doors problem"
date: "07-AUG-2011"
revision: "1.0"
 
class
APPLICATION
 
create
make
 
feature {NONE} -- Initialization
 
doors: LINKED_LIST [DOOR]
-- A set of doors
once
create Result.make
end
 
make
-- Run application.
local
count, i: INTEGER
do
--initialize doors
count := 100
from
i := 1
until
i > count
loop
doors.extend (create {DOOR}.make (i, false))
i := i + 1
end
 
-- toggle doors
from
i := 1
until
i > count
loop
across
doors as this
loop
if this.item.address \\ i = 0 then
this.item.open := not this.item.open
end
end -- across doors
i := i + 1
end -- for i
 
-- print results
doors.do_all (agent (door: DOOR)
do
if door.open then
io.put_string ("Door " + door.address.out + " is open.")
elseif not door.open then
io.put_string ("Door " + door.address.out + " is closed.")
end
io.put_new_line
end)
end -- make
 
end -- APPLICATION

file: door.e

note
description: "A door with an address and an open or closed state."
date: "07-AUG-2011"
revision: "1.0"
 
class
DOOR
 
create
make
 
feature -- initialization
 
make (addr: INTEGER; status: BOOLEAN)
-- create door with address and status
require
valid_address: addr /= '%U'
valid_status: status /= '%U'
do
address := addr
open := status
ensure
address_set: address = addr
status_set: open = status
end
 
feature -- access
 
address: INTEGER
 
open: BOOLEAN assign set_open
 
feature -- mutators
 
set_open (status: BOOLEAN)
require
valid_status: status /= '%U'
do
open := status
ensure
open_updated: open = status
end
 
end

[edit] Ela

Standard Approach

open generic
 
type Door = Open | Closed
deriving Show
 
gate [] _ = []
gate (x::xs) (y::ys)
| x == y = Open :: gate xs ys
| else = Closed :: gate xs ys
 
run n = gate [1..n] [& k*k \\ k <- [1..]]

Alternate Approach

open list
run n = takeWhile (<n) [& k*k \\ k <- [1..]]

[edit] Elixir

defmodule HundredDoors do
 
def doors() do
Enum.to_list(Stream.take(Stream.cycle([false]), 100))
end
 
def toggle(doors, n) do
Enum.take(doors, n) ++ [not Enum.at(doors,n)] ++ Enum.drop(doors,n+1)
end
 
def toggle_every(doors, n) do
Enum.reduce( Enum.take_every((n-1)..99, n), doors, fn(n, acc) -> toggle(acc, n) end )
end
 
end
 
# unoptimized
final_state = Enum.reduce(1..100, HundredDoors.doors, fn(n, acc) -> HundredDoors.toggle_every(acc, n) end)
 
# optimized
final_state = Enum.reduce(1..10, HundredDoors.doors, fn(n, acc) -> HundredDoors.toggle(acc, n*n-1) end)
 
open_doors = Enum.map(Enum.filter( Enum.with_index(final_state), fn({door,_}) -> door end ),
fn({_,index}) -> index+1 end)
 
IO.puts "All doors are closed except these: #{inspect open_doors}"
Output:
All doors are closed except these: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]


[edit] Emacs Lisp

Unoptimized

(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))

[edit] Erlang

non-optimized

 
-module(hundoors).
 
-export([go/0]).
 
toggle(closed) -> open;
toggle(open) -> closed.
 
go() -> go([closed || _ <- lists:seq(1, 100)],[], 1, 1).
go([], L, N, _I) when N =:= 101 -> lists:reverse(L);
go([], L, N, _I) -> go(lists:reverse(L), [], N + 1, 1);
go([H|T], L, N, I) ->
H2 = case I rem N of
0 -> toggle(H);
_ -> H
end,
go(T, [H2|L], N, I + 1).
 


optimized

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)].

[edit] Euler Math Toolbox

 
>function Doors () ...
$ doors:=zeros(1,100);
$ for i=1 to 100
$ for j=i to 100 step i
$ doors[j]=!doors[j];
$ end;
$ end;
$ return doors
$endfunction
>nonzeros(Doors())
[ 1 4 9 16 25 36 49 64 81 100 ]
 

[edit] Euphoria

unoptimised

-- doors.ex
include std/console.e
sequence doors
doors = repeat( 0, 100 ) -- 1 to 100, initialised to false
 
for pass = 1 to 100 do
for door = pass to 100 by pass do
--printf( 1, "%d", doors[door] )
--printf( 1, "%d", not doors[door] )
doors[door] = not doors[door]
end for
end for
 
sequence oc
 
for i = 1 to 100 do
if doors[i] then
oc = "open"
else
oc = "closed"
end if
printf( 1, "door %d is %s\n", { i, oc } )
end for
 

[edit] F#

Requires #light in versions of F# prior to 2010 beta.

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
 

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.

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 |]

[edit] Factor

Unoptimized

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 ;

Optimized

 
USING:
formatting
math math.primes.factors math.ranges
sequences ;
IN: rosetta-doors2
 
: main ( -- )
100 [1,b] [ divisors length odd? ] filter "Open %[%d, %]\n" printf ;
 

[edit] Falcon

Unoptimized code

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
 

Optimized code

 
for door in [ 1 : 101 ]: > "Door ", $door, " is: ", fract( door ** 0.5 ) ? "closed" : "open"

[edit] Fantom

Unoptimized

 
states := (1..100).toList
100.times |i| {
states = states.map |state| { state % (i+1) == 0 ? -state : +state }
}
echo("Open doors are " + states.findAll { it < 0 }.map { -it })
 

Optimized

 
echo("Open doors are " + (1..100).toList.findAll { it.toFloat.pow(0.5f).toInt.pow(2) == it})
 

[edit] FBSL

Unoptimised

#AppType Console
 
DIM doors[], n AS INTEGER = 100
 
FOR DIM i = 1 TO n
FOR DIM j = i TO n STEP i
doors[j] = NOT doors[j]
NEXT
NEXT
 
FOR i = 1 TO n
IF doors[i] THEN PRINT "Door ", i, " is open"
NEXT
 
Pause

Optimised (by ML)

#APPTYPE CONSOLE
 
DIM i = 0, j = 0, door = 1
 
WHILE INCR(i) < 101
IF i = door THEN
PRINT "Door ", door, " open"
INCR(door, INCR((INCR(j) << 1)))
END IF
WEND
 
PAUSE

[edit] friendly interactive shell

Unoptimized

# Set doors to empty list
set doors
 
# Initialize doors arrays
for i in (seq 100)
set doors[$i] 0
end
 
for i in (seq 100)
set j $i
while test $j -le 100
# Logical not on doors
set doors[$j] (math !$doors[$j])
set j (math $j + $i)
end
end
 
# Print every door
for i in (seq (count $doors))
echo -n "$i "
if test $doors[$i] -eq 0
echo closed
else
echo open
end
end
 

Optimized

# Set doors to empty list
set doors
 
for i in (seq 100)
set doors[(math "$i * $i")] 1
echo -n "$i "
if test $doors[$i] -eq 1
echo open
else
echo closed
end
end

[edit] Forth

Unoptimized

: toggle ( c-addr -- )  \ toggle the byte at c-addr
dup c@ 1 xor swap c! ;
 
100 1+ ( 1-based indexing ) constant ndoors
create doors ndoors allot
 
: init ( -- ) doors ndoors erase ; \ close all doors
 
: pass ( n -- ) \ toggle every nth door
ndoors over do
doors i + toggle
dup ( n ) +loop drop ;
 
: run ( -- ) ndoors 1 do i pass loop ;
: display ( -- ) \ display open doors
ndoors 1 do doors i + c@ if i . then loop cr ;
 
init run display

Optimized

: squared ( n -- n' )  dup * ;
: doors ( n -- )
1 begin 2dup squared >= while
dup squared .
1+ repeat 2drop ;
100 doors

[edit] Fortran

Works with: Fortran version ISO 90 and later

unoptimized

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

optimized

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

[edit] Frink

 
doors = new array[[101], false]
for pass=1 to 100
for door=pass to 100 step pass
doors@door = ! doors@door
 
print["Open doors: "]
for door=1 to 100
if doors@door
print["$door "]
 

[edit] GAP

doors := function(n)
local a,j,s;
a := [ ];
for j in [1 .. n] do
a[j] := 0;
od;
for s in [1 .. n] do
j := s;
while j <= n do
a[j] := 1 - a[j];
j := j + s;
od;
od;
return Filtered([1 .. n], j -> a[j] = 1);
end;
 
doors(100);
# [ 1, 4, 9, 16, 25, 36, 49, 64, 81, 100 ]

[edit] GML

var doors,a,i;
//Sets up the array for all of the doors.
for (i = 1; i<=100; i += 1)
{
doors[i]=0;
}
 
//This first for loop goes through and passes the interval down to the next for loop.
for (i = 1; i <= 100; i += 1;)
{
//This for loop opens or closes the doors and uses the interval(if interval is 2 it only uses every other etc..)
for (a = 0; a <= 100; a += i;)
{
//Opens or closes a door.
doors[a] = !doors[a];
}
}
open_doors = '';
 
//This for loop goes through the array and checks for open doors.
//If the door is open it adds it to the string then displays the string.
for (i = 1; i <= 100; i += 1;)
{
if (doors[i] == 1)
{
open_doors += "Door Number "+string(i)+" is open#";
}
}
show_message(open_doors);
game_end();

[edit] Go

unoptimized

package main
 
import "fmt"
 
func main() {
doors := make([]bool, 100)
 
// the 100 passes called for in the task description
for pass := 1; pass <= 100; pass++ {
for door := pass-1; door < 100; door += pass {
doors[door] = !doors[door]
}
}
 
// one more pass to answer the question
for i, v := range doors {
if v {
fmt.Print("1")
} else {
fmt.Print("0")
}
 
if i%10 == 9 {
fmt.Print("\n")
} else {
fmt.Print(" ")
}
 
}
}

Output:

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 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1

optimized

package main
 
import "fmt"
 
func main() {
var door int = 1
var incrementer = 0
 
for current := 1; current <= 100; current++ {
fmt.Printf("Door %d ", current)
 
if current == door {
fmt.Printf("Open\n")
incrementer++
door += 2*incrementer + 1
} else {
fmt.Printf("Closed\n")
}
}
}

[edit] Golfscript

100:c;[{0}c*]:d;
c,{.c,>\)%{.d<\.d=1^\)d>++:d;}/}/
[c,{)"door "\+" is"+}%d{{"open"}{"closed"}if}%]zip
{" "*puts}/

optimized with sqrt (Original version of GolfScript has no sqrt operator, but it can be added easily; the code was tested using a work-in-progress C interpreter for a language compatible enough with Golfscript)

100,{)}%
{:d.sqrt 2?=
{"open"}{"close"}if"door "d+" is "+\+puts}/

optimized without sqrt

[{"close"}100*]:d;
10,{)2?(.d<\["open"]\)d>++:d;}/
[100,{)"door "\+" is"+}%d]zip
{" "*puts}/

[edit] Gosu

unoptimized

 
uses java.util.Arrays
 
var doors = new boolean[100]
Arrays.fill( doors, false )
 
for( pass in 1..100 ) {
var counter = pass-1
while( counter < 100 ) {
doors[counter] = !doors[counter]
counter += pass
}
}
 
for( door in doors index i ) {
print( "door ${i+1} is ${door ? 'open' : 'closed'}" )
}
 
 

optimized

 
var door = 1
var delta = 0
 
for( i in 1..100 ) {
if( i == door ) {
print( "door ${i} is open" )
delta++
door += 2*delta + 1
} else {
print( "door ${i} is closed" )
}
}
 

[edit] Groovy

unoptimized

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'}.")
}

optimized a Using square roots

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

optimized b Without using square roots

doors = ['closed'] * 100
(1..10).each { doors[it**2 - 1] = 'open' }
(0..99).each {
println("Door #${it + 1} is ${doors[it]}.")
}

[edit] Haskell

unoptimized

data Door = Open | Closed deriving Show
 
toggle Open = Closed
toggle Closed = Open
 
toggleEvery :: [Door] -> Int -> [Door]
toggleEvery xs k = zipWith ($) fs xs
where fs = cycle $ (replicate (k-1) id) ++ [toggle]
 
run n = foldl toggleEvery (replicate n Closed) [0..n]

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..]]

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

run n = takeWhile (< n) [k*k | k <- [1..]]

[edit] Haxe

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

[edit] HicEst

Unoptimized

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")

Optimized

door = 1 - open ! = closed
DO i = 1, n^0.5
door(i*i) = open
ENDDO
DLG(Text=door, TItle=SUM(door)//" doors open")

[edit] Icon and Unicon

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 run time.

Unoptimized solution.

 
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
 

Optimized solution.

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

or

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

[edit] Inform 7

Works with: Z-machine version 8
Hallway is a room.
 
A toggle door is a kind of thing.
A toggle door can be open or closed. It is usually closed.
A toggle door has a number called the door number.
Understand the door number property as referring to a toggle door.
Rule for printing the name of a toggle door: say "door #[door number]".
 
There are 100 toggle doors.
 
When play begins (this is the initialize doors rule):
let the next door number be 1;
repeat with D running through toggle doors:
now the door number of D is the next door number;
increment the next door number.
 
To toggle (D - open toggle door): now D is closed.
To toggle (D - closed toggle door): now D is open.
 
When play begins (this is the solve puzzle rule):
let the door list be the list of toggle doors;
let the door count be the number of entries in the door list;
repeat with iteration running from 1 to 100:
let N be the iteration;
while N is less than the door count:
toggle entry N in the door list;
increase N by the iteration;
say "Doors left open: [list of open toggle doors].";
end the story.

[edit] Informix 4GL

 
MAIN
DEFINE
i, pass SMALLINT,
doors ARRAY[100] OF SMALLINT
 
FOR i = 1 TO 100
LET doors[i] = FALSE
END FOR
 
FOR pass = 1 TO 100
FOR i = pass TO 100 STEP pass
LET doors[i] = NOT doors[i]
END FOR
END FOR
 
FOR i = 1 TO 100
IF doors[i]
THEN DISPLAY i USING "Door <<& is open"
ELSE DISPLAY i USING "Door <<& is closed"
END IF
END FOR
END MAIN
 

[edit] Io

simple boolean list solution:

doors := List clone
100 repeat(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))

Optimized solution:

(Range 1 to(10) asList) foreach(v, "Door #{v ** 2} is open." interpolate println)
Sample 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.

[edit] Ioke

Unoptimized Object Oriented solution.

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

[edit] 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 ...
~:/ 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 ...

optimized

   (e. *:) 1+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 ...
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 ...

with formatting

   'these doors are open' ; >: I. (>:i.100) e. *: i.11
┌────────────────────┬───────────────────────────┐
│these doors are open│1 4 9 16 25 36 49 64 81 100
└────────────────────┴───────────────────────────┘
 
 

[edit] Java

unoptimized

 
public class HundredDoors {
public static void main(String[] args) {
boolean[] doors = new boolean[101];
for (int i = 1; i <= 100; i++) {
for (int j = i; j <= 100; j++) {
if(j % i == 0) doors[j] = !doors[j];
}
}
for (int i = 1; i <= 100; i++) {
System.out.printf("Door %d: %s%n", i, doors[i] ? "open" : "closed");
}
}
}

If a boolean array is required.

 
public class Doors
{
public static void main(String[] args)
{
boolean[] doors=new boolean[100];
for(int i=0;i<10;i++)
doors[i*(i+2)]=true;
for(int i=0;i<100;i++)
System.out.println("Door #"+(i+1)+" is"+(doors[i]?"open.":" closed."));
}
}
 

If only printing the result is required.

 
public class Doors
{
public static void main(String[] args)
{
for(int i=0;i<10;i++)
System.out.println("Door #"+(i*(i+2)+1)+" is open.");
}
}
 

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.

optimized

public class Doors
{
public static void main(final 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."));
}
}

optimized 2

public class Doors
{
public static void main(final String[] args)
{
StringBuilder sb = new StringBuilder();
 
for (int i = 1; i <= 10; i++)
sb.append("Door #").append(i*i).append(" is open\n");
 
System.out.println(sb.toString());
}
}

optimized 3

public class Doors{
public static void main(String[] args){
int i;
for(i = 1; i < 101; i++){
double sqrt = Math.sqrt(i);
if(sqrt != (int)sqrt){
System.out.println("Door " + i + " is closed");
}else{
System.out.println("Door " + i + " is open");
}
}
}
}

[edit] JavaScript

[edit] ES5

for (var door = 1; door <= 100; i++) {
var sqrt = Math.sqrt(door);
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
}
Array.apply(null, { length: 100 })
.map(function(v, i) { return i + 1; })
.forEach(function(door) {
var sqrt = Math.sqrt(door);
 
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
});

[edit] ES6

 
Array.apply(null, { length: 100 })
.map((v, i) => i + 1)
.forEach(door => {
var sqrt = Math.sqrt(door);
 
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
});


// Array comprehension style
[ for (i of Array.apply(null, { length: 100 })) i ].forEach((_, i) => {
var door = i + 1
var sqrt = Math.sqrt(door);
 
if (sqrt === (sqrt | 0)) {
console.log("Door %d is open", door);
}
});

The result is always:

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

[edit] Julia

unoptimized:
-falses(100) creates a 100-element Bool array filled with false values
-'b in a:a:100' translates to 'start:step:end'
-string concatenation by '*'

 
doors = falses(100)
for a = 1:100, b in a:a:100
doors[b] = !doors[b]
end
for a = 1:100 println("Door $a is " * (doors[a] ? "open" : "close") ) end

ultra-optimized:

for i = 1:10 println("Door $(i^2) is open") end


[edit] K

unoptimized / converted from Q .

 `closed `open ![ ; 2 ] @ #:' 1 _ = ,/ &:' 0 = t !\:/: t : ! 101

optimized / 1 origin indices

 ( 1 + ! 10 ) ^ 2

/ As parameterized function :

 { ( 1 + ! _ x ^ % 2 ) ^ 2 } 100 

[edit] Kotlin

fun oneHundredDoors(): List<Int> {
val doors = Array<Boolean>(100, { false })
 
for (i in 0..99)
for (j in i..99 step (i + 1))
doors[j] = !doors[j]
 
return IndexIterator(doors.iterator()).filter { it.second }
.map { it.first + 1 }
.toList()
}

[edit] LabVIEW

This image is a VI Snippet, an executable image of LabVIEW code. The LabVIEW version is shown on the top-right hand corner. You can download it, then drag-and-drop it onto the LabVIEW block diagram from a file browser, and it will appear as runnable, editable code.
100doors.png

Optimized

This image is a VI Snippet, an executable image of LabVIEW code. The LabVIEW version is shown on the top-right hand corner. You can download it, then drag-and-drop it onto the LabVIEW block diagram from a file browser, and it will appear as runnable, editable code.
LabVIEW 100 doors.png

[edit] Lasso

[edit] Loop

loop(100) => {^
local(root = math_sqrt(loop_count))
local(state = (#root == math_ceil(#root) ? '<strong>open</strong>' | 'closed'))
#state != 'closed' ? 'Door ' + loop_count + ': ' + #state + '<br>'
^}
Output:
Door 1: open
Door 4: open
Door 9: open
Door 16: open
Door 25: open
Door 36: open
Door 49: open
Door 64: open
Door 81: open
Door 100: open

[edit] Lhogho

This implementation defines 100 variables, named "1 through "100, rather than using a list. Thanks to Pavel Boytchev, the author of Lhogho, for help with the code.

to doors
;Problem 100 Doors
;Lhogho
 
for "p [1 100]
[
make :p "false
]
 
for "a [1 100 1]
[
for "b [:a 100 :a]
[
if :b < 101
[
make :b not thing :b
]
]
]
 
for "c [1 100]
[
if thing :c
[
(print "door :c "is "open)
]
]
end
 
doors

[edit] Liberty BASIC

dim doors(100)
for pass = 1 to 100
for door = pass to 100 step pass
doors(door) = not(doors(door))
next door
next pass
print "open doors ";
for door = 1 to 100
if doors(door) then print door;" ";
next door

[edit]

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

[edit] LOLCODE

HAI 1.3
 
I HAS A doors ITZ A BUKKIT
IM IN YR hallway UPPIN YR door TIL BOTH SAEM door AN 100
doors HAS A SRS door ITZ FAIL BTW, INISHULIZE ALL TEH DOORZ AS CLOZD
IM OUTTA YR hallway
 
IM IN YR hallway UPPIN YR pass TIL BOTH SAEM pass AN 100
I HAS A door ITZ pass
IM IN YR passer
doors'Z SRS door R NOT doors'Z SRS door
door R SUM OF door AN SUM OF pass AN 1
DIFFRINT door AN SMALLR OF door AN 99, O RLY?
YA RLY, GTFO
OIC
IM OUTTA YR passer
IM OUTTA YR hallway
 
IM IN YR printer UPPIN YR door TIL BOTH SAEM door AN 100
VISIBLE "Door #" SUM OF door AN 1 " is "!
doors'Z SRS door, O RLY?
YA RLY, VISIBLE "open."
NO WAI, VISIBLE "closed."
OIC
IM OUTTA YR printer
 
KTHXBYE

[edit] 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

[edit] 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

[edit] Maple

 
NDoors := proc( N :: posint )
# Initialise, using 0 to represent "closed"
local doors := Array( 1 .. N, 'datatype' = 'integer'[ 1 ] );
# Now do N passes
for local pass from 1 to N do
for local door from pass by pass while door <= N do
doors[ door ] := 1 - doors[ door ]
end do
end do;
# Output
for door from 1 to N do
printf( "Door %d is %s.\n", door, `if`( doors[ door ] = 0, "closed", "open" ) )
end do;
# Since this is a printing routine, return nothing.
NULL
end proc:
 

To solve the problem, call it with 100 as argument (output not shown here).

 
> NDoors( 100 );
 

Here is the optimised version, which outputs only the open doors.

 
> seq( i^2, i = 1 .. isqrt( 100 ) );
1, 4, 9, 16, 25, 36, 49, 64, 81, 100
 

Alternatively,

 
> [seq]( 1 .. 10 )^~2;
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
 

[edit] Mathematica

unoptimized 1

n=100;
tmp=ConstantArray[-1,n];
Do[tmp[[i;;;;i]]*=-1;,{i,n}];
Do[Print["door ",i," is ",If[tmp[[i]]==-1,"closed","open"]],{i,1,Length[tmp]}]

unoptimized 2

f[n_] = "Closed"; 
Do[Do[If[f[n] == "Closed", f[n] = "Open", f[n] = "Closed"], {n, k, 100, k}], {k, 1, 100}];
Table[f[n], {n, 1, 100}]

optimized 1

Do[Print["door ",i," is ",If[IntegerQ[Sqrt[i]],"open","closed"]],{i,100}]

optimized 2

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

optimized 3

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"];
];
]

These will only give the indices for the open doors: unoptimized 2

Pick[Range[100], Xor@@@Array[Divisible[#1,#2]&, {100,100}]]

optimized 4

Range[Sqrt[100]]^2

[edit] MATLAB / Octave

[edit] Iterative Method

Unoptimized

 
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
 

Optimized

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

More Optimized

 
a = zeros(100,1);
for counter = 1:sqrt(100);
a(counter^2) = 1;
end
a
 

[edit] Vectorized Method

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

[edit] Known-Result Method

 
doors((1:10).^2) = 1;
 
doors
 

[edit] Maxima

doors(n) := block([v], local(v),
v: makelist(true, n),
for i: 2 thru n do
for j: i step i thru n do v[j]: not v[j],
sublist_indices(v, 'identity));

Usage:

doors(100);
/* [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] */

[edit] 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))
)

[edit] Mercury

:- module doors.
:- interface.
:- import_module array, io, int.
 
:- type door ---> open ; closed.
:- type doors == array(door).
 
:- func toggle(door) = door.
:- pred walk(int::in, doors::in, doors::out) is semidet.
:- pred walks(int::in, int::in, doors::in, doors::out) is det.
 
:- pred main(io::di, io::uo) is det.
 
:- implementation.
 
toggle(open) = closed.
toggle(closed) = open.
 
walk(N, !D) :- walk(N, N, !D).
 
:- pred walk(int::in, int::in, doors::in, doors::out) is semidet.
walk(At, By, !D) :-
semidet_lookup(!.D, At - 1, Door),
slow_set(!.D, At - 1, toggle(Door), !:D),
( walk(At + By, By, !D) -> true ; true ).
 
walks(N, End, !D) :-
( N =< End, walk(N, !D) -> walks(N + 1, End, !D) ; true ).
 
main(!IO) :-
io.write(Doors1, !IO), io.nl(!IO),
array.init(100, closed, Doors0),
walks(1, 100, Doors0, Doors1).

[edit] 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

[edit] MIPS Assembly

.data
doors: .space 100
num_str: .asciiz "Number "
comma_gap: .asciiz " is "
newline: .asciiz "\n"
 
.text
main:
# Clear all the cells to zero
li $t1, 100
la $t2, doors
clear_loop:
sb $0, ($t2)
add $t2, $t2, 1
sub $t1, $t1, 1
bnez $t1, clear_loop
 
# Now start the loops
li $t0, 1 # This will the the step size
li $t4, 1 # just an arbitrary 1
loop1:
move $t1, $t0 # Counter
la $t2, doors # Current pointer
add $t2, $t2, $t0
addi $t2, $t2, -1
loop2:
lb $t3, ($t2)
sub $t3, $t4, $t3
sb $t3, ($t2)
add $t1, $t1, $t0
add $t2, $t2, $t0
ble $t1, 100, loop2
 
addi $t0, $t0, 1
ble $t0, 100, loop1
 
# Now display everything
la $t0, doors
li $t1, 1
loop3:
li $v0, 4
la $a0, num_str
syscall
 
li $v0, 1
move $a0, $t1
syscall
 
li $v0, 4
la $a0, comma_gap
syscall
 
li $v0, 1
lb $a0, ($t0)
syscall
 
li $v0, 4,
la $a0, newline
syscall
 
addi $t0, $t0, 1
addi $t1, $t1, 1
bne $t1, 101 loop3
 

[edit] Mirah

import java.util.ArrayList
 
class Door
:state
 
def initialize
@state=false
end
 
def closed?; !@state; end
def open?; @state; end
 
def close; @state=false; end
def open; @state=true; end
 
def toggle
if closed?
open
else
close
end
end
 
def toString; Boolean.toString(@state); end
end
 
doors=ArrayList.new
1.upto(100) do
doors.add(Door.new)
end
 
1.upto(100) do |multiplier|
index = 0
doors.each do |door|
Door(door).toggle if (index+1)%multiplier == 0
index += 1
end
end
 
i = 0
doors.each do |door|
puts "Door #{i+1} is #{door}."
i+=1
end
 

[edit] mIRC Scripting Language

var %d = $str(0 $+ $chr(32),100), %m = 1
while (%m <= 100) {
var %n = 1
while ($calc(%n * %m) <= 100) {
var %d = $puttok(%d,$iif($gettok(%d,$calc(%n * %m),32),0,1),$calc(%n * %m),32)
inc %n
}
inc %m
}
echo -ag All Doors (Boolean): %d
var %n = 1
while (%n <= $findtok(%d,1,0,32)) {
var %t = %t $findtok(%d,1,%n,32)
inc %n
}
echo -ag Open Door Numbers: %t

[edit] ML/I

MCSKIP "WITH" NL
"" 100 doors
MCINS %.
MCSKIP MT,<>
"" Doors represented by P1-P100, 0 is closed
MCPVAR 100
"" Set P variables to 0
MCDEF ZEROPS WITHS NL AS <MCSET T1=1
%L1.MCSET PT1=0
MCSET T1=T1+1
MCGO L1 UNLESS T1 EN 101
>
ZEROPS
"" Generate door state
MCDEF STATE WITHS () AS <MCSET T1=%A1.
MCGO L1 UNLESS T1 EN 0
closed<>MCGO L0
%L1.open>
"" Main macro - no arguments
"" T1 is pass number
"" T2 is door number
MCDEF DOORS WITHS NL
AS <MCSET T1=1
"" pass loop
%L1.MCGO L4 IF T1 GR 100
"" door loop
MCSET T2=T1
%L2.MCGO L3 IF T2 GR 100
MCSET PT2=1-PT2
MCSET T2=T2+T1
MCGO L2
%L3.MCSET T1=T1+1
MCGO L1
%L4."" now output the result
MCSET T1=1
%L5.door %T1. is STATE(%PT1.)
MCSET T1=T1+1
MCGO L5 UNLESS T1 GR 100
>
"" Do it
DOORS

[edit] MMIX

See 100 doors/MMIX

[edit] Modula-2

unoptimized

MODULE Doors;
IMPORT InOut;
 
TYPE State = (Closed, Open);
TYPE List = ARRAY [1 .. 100] OF State;
 
VAR
Doors: List;
I, J: CARDINAL;
 
BEGIN
FOR I := 1 TO 100 DO
FOR J := 1 TO 100 DO
IF J MOD I = 0 THEN
IF Doors[J] = Closed THEN
Doors[J] := Open
ELSE
Doors[J] := Closed
END
END
END
END;
 
FOR I := 1 TO 100 DO
InOut.WriteCard(I, 3);
InOut.WriteString(' is ');
 
IF Doors[I] = Closed THEN
InOut.WriteString('Closed.')
ELSE
InOut.WriteString('Open.')
END;
 
InOut.WriteLn
END
END Doors.

optimized

MODULE DoorsOpt;
IMPORT InOut;
 
TYPE State = (Closed, Open);
TYPE List = ARRAY [1 .. 100] OF State;
 
VAR
Doors: List;
I: CARDINAL;
 
BEGIN
FOR I := 1 TO 10 DO
Doors[I*I] := Open
END;
 
FOR I := 1 TO 100 DO
InOut.WriteCard(I, 3);
InOut.WriteString(' is ');
IF Doors[I] = Closed THEN
InOut.WriteString('Closed.')
ELSE
InOut.WriteString('Open.')
END;
InOut.WriteLn
END
END DoorsOpt.

[edit] Modula-3

unoptimized

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.

optimized

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.

[edit] 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

[edit] MoonScript

is_open = [false for door = 1,100]
 
for pass = 1,100
for door = pass,100,pass
is_open[door] = not is_open[door]
 
for i,v in ipairs is_open
print "Door #{i}: " .. if v then 'open' else 'closed'

[edit] 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.

[edit] NetRexx

unoptimized

/* NetRexx */
options replace format comments java crossref savelog symbols binary
 
True = Rexx(1 == 1)
False = Rexx(\True)
 
doors = False
 
loop i_ = 1 to 100
loop j_ = 1 to 100
if 0 = (j_ // i_) then doors[j_] = \doors[j_]
end j_
end i_
 
loop d_ = 1 to 100
if doors[d_] then state = 'open'
else state = 'closed'
 
say 'Door Nr.' Rexx(d_).right(4) 'is' state
end d_
 

optimized (Based on the Java 'optimized' version)

Translation of: Java
/* NetRexx */
options replace format comments java crossref savelog symbols binary
 
True = (1 == 1)
False = \True
 
doors = boolean[100]
 
loop i_ = 0 to 9
doors[(i_ + 1) * (i_ + 1) - 1] = True;
end i_
 
loop i_ = 0 to 99
if doors[i_] then state = 'open'
else state = 'closed'
 
say 'Door Nr.' Rexx(i_ + 1).right(4) 'is' state
end i_
 

optimized 2 (Based on the Java 'optimized 2' version)

Translation of: Java
/* NetRexx */
options replace format comments java crossref savelog symbols binary
 
resultstring = ''
 
loop i_ = 1 to 10
resultstring = resultstring || 'Door Nr.' Rexx(i_ * i_).right(4) 'is open\n'
end i_
 
say resultstring
 

optimized 3

/* NetRexx */
 
loop i = 1 to 10
say 'Door Nr.' i * i 'is open.'
end i
 
 

[edit] NewLisp

(define (status door-num)
(let ((x (int (sqrt door-num))))
(if
(= (* x x) door-num) (string "Door " door-num " Open")
(string "Door " door-num " Closed"))))
 
(dolist (n (map status (sequence 1 100)))
(println n))
 

[edit] Nimrod

unoptimized:

 
from strutils import format
 
proc check_doors() =
const n = 100
var is_open : array[1..n, bool] # auto-initialized to false
# pass over the doors n times
for pass in 1..n:
var i = pass
while i <= n:
is_open[i] = not is_open[i]
i += pass
# print the result
for door in 1..n:
echo format("door $1 is $2.", door, (if is_open[door]: "open" else: "closed"))
 
check_doors()
 

[edit] Objeck

optimized

 
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();
};
};
}
}
}
 

[edit] OCaml

unoptimized

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))

optimized

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))

[edit] 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

see also the solutions in Matab. They will work in Octave, too.

[edit] ooRexx

 
doors = .array~new(100) -- array containing all of the doors
do i = 1 to doors~size -- initialize with a collection of closed doors
doors[i] = .door~new(i)
end
 
do inc = 1 to doors~size
do d = inc to doors~size by inc
doors[d]~toggle
end
end
say "The open doors after 100 passes:"
do door over doors
if door~isopen then say door
end
 
::class door -- simple class to represent a door
::method init -- initialize an instance of a door
expose id state -- instance variables of a door
use strict arg id -- set the id
state = .false -- initial state is closed
 
::method toggle -- toggle the state of the door
expose state
state = \state
 
::method isopen -- test if the door is open
expose state
return state
 
::method string -- return a string value for a door
expose state id
if state then return "Door" id "is open"
else return "Door" id "is closed"
 
::method state -- return door state as a descriptive string
expose state
if state then return "open"
else return "closed"
 
 

The four examples in the Rexx section also run unchanged under ooRexx

[edit] OpenEdge/Progress

DEFINE VARIABLE lopen   AS LOGICAL     NO-UNDO EXTENT 100.
DEFINE VARIABLE idoor AS INTEGER NO-UNDO.
DEFINE VARIABLE ipass AS INTEGER NO-UNDO.
DEFINE VARIABLE cresult AS CHARACTER NO-UNDO.
 
DO ipass = 1 TO 100:
idoor = 0.
DO WHILE idoor <= 100:
idoor = idoor + ipass.
IF idoor <= 100 THEN
lopen[ idoor ] = NOT lopen[ idoor ].
END.
END.
 
DO idoor = 1 TO 100:
cresult = cresult + STRING( lopen[ idoor ], "1 /0 " ).
IF idoor MODULO 10 = 0 THEN
cresult = cresult + "~r":U.
END.
 
MESSAGE cresult VIEW-AS ALERT-BOX.
 

[edit] OxygenBasic

def    doors 100
int    door[doors],i ,j, c
string cr,tab,pr
'
for i=1 to doors
  for j=i to doors step i
    door[j]=1-door[j]
    if door[j] then c++ else c--
  next
next
'
cr=chr(13) chr(10)
pr="Doors Open: " c cr cr 
'
for i=1 to doors
   if door[i] then pr+=i cr
next
print pr

[edit] 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
}

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.

[edit] PARI/GP

Unoptimized version.

 
v=vector(d=100);/*set 100 closed doors*/
for(i=1,d,forstep(j=i,d,i,v[j]=1-v[j]));
for(i=1,d,if(v[i],print("Door ",i," is open.")))
 

Optimized version.

for(n=1,sqrt(100),print("Door ",n^2," is open."))

[edit] 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.

Optimized version.

program OneHundredDoors;
 
{$APPTYPE CONSOLE}
 
uses
math, sysutils;
 
var
AOpendoors : String;
ACloseDoors : String;
i : Integer;
 
begin
for i := 1 to 100 do
begin
if (sqrt(i) = floor(sqrt(i))) then
AOpenDoors := AOpenDoors + IntToStr(i) + ';'
else
ACloseDoors := ACloseDoors + IntToStr(i) +';';
end;
 
WriteLn('Open doors: ' + AOpenDoors);
WriteLn('Close doors: ' + ACloseDoors);
end.

[edit] Perl

unoptimized

Works with: Perl version 5.x
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;

optimized

Works with: Perl version 5.x
print "Door $_ is open\n" for map $_**2, 1 .. 10;
print "Door $_ is ", qw"closed open"[int sqrt == sqrt], "\n" for 1..100;
while( ++$i <= 100 )
{
$root = sqrt($i);
if ( int( $root ) == $root )
{
print "Door $i is open\n";
}
else
{
print "Door $i is closed\n";
}
}

[edit] Perl5i

 
use perl5i::2;
 
package doors {
 
use perl5i::2;
use Const::Fast;
 
const my $OPEN => 1;
const my $CLOSED => 0;
 
# ----------------------------------------
# Constructor: door->new( @args );
# input: N - how many doors?
# returns: door object
#
method new($class: @args ) {
my $self = bless {}, $class;
$self->_init( @args );
return $self;
}
 
# ----------------------------------------
# class initializer.
# input: how many doors?
# sets N, creates N+1 doors ( door zero is not used ).
#
method _init( $N ) {
$self->{N} = $N;
$self->{doors} = [ ($CLOSED) x ($N+1) ];
}
 
# ----------------------------------------
# $self->toggle( $door_number );
# input: number of door to toggle.
# OPEN a CLOSED door; CLOSE an OPEN door.
#
method toggle( $which ) {
$self->{doors}[$which] = ( $self->{doors}[$which] == $OPEN
 ? $CLOSED
 : $OPEN
);
}
 
# ----------------------------------------
# $self->toggle_n( $cycle );
# input: number.
# Toggle doors 0, $cycle, 2 * $cycle, 3 * $cycle, .. $self->{N}
#
method toggle_n( $n ) {
$self->toggle($_)
for map { $n * $_ }
( 1 .. int( $self->{N} / $n) );
 
}
 
# ----------------------------------------
# $self->toggle_all();
# Toggle every door, then every other door, every third door, ...
#
method toggle_all() {
$self->toggle_n( $_ ) for ( 1 .. $self->{N} );
}
 
 
# ----------------------------------------
# $self->print_open();
# Print list of which doors are open.
#
method print_open() {
say join ', ', grep { $self->{doors}[$_] == $OPEN } ( 1 ... $self->{N} );
}
}
 
# ----------------------------------------------------------------------
# Main Thread
#
my $doors = doors->new(100);
$doors->toggle_all();
$doors->print_open();
 

[edit] Perl 6

unoptimized
Works with: Rakudo version 2010.07"
my @doors = False xx 101;
 
($_ = !$_ for @doors[0, * + $_ ...^ * > 100]) for 1..100;
 
say "Door $_ is ", <closed open>[ @doors[$_] ] for 1..100;

optimized

say "Door $_ is open" for map {$^n ** 2}, 1..10;

Here's a version using the cross meta-operator instead of a map:

 say "Door $_ is open" for 1..10 X** 2;

This one prints both opened and closed doors:

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

[edit] PHL

[edit] unoptimized

module doors;
 
extern printf;
 
@Integer main [
@Array<@Boolean> doors = new @Array<@Boolean>.init(100);
var i = 1;
while (i <= 100) {
var j = i-1;
while (j < 100) {
doors.set(j, doors.get(j)::not);
j = j + i;
}
i = i::inc;
}
i = 0;
while (i < 100) {
printf("%i %s\n", i+1, iif(doors.get(i), "open", "closed"));
i = i::inc;
}
return 0;
]

[edit] optimized

Translation of: C#
module var;
 
extern printf;
 
@Integer main [
var door = 1;
var incrementer = 0;
var current = 1;
while (current <= 100)
{
printf("Door %i ", current);
if (current == door)
{
printf("open\n");
incrementer = incrementer::inc;
door = door + 2 * incrementer + 1;
}
else
printf("closed\n");
 
current = current + 1;
 
}
 
return 0;
]

[edit] PHP

See: Demo optimized

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

unoptimized

<?php
$toggleState = array('open' => 'closed', 'closed' => 'open');
$doors = array_fill(1, 100, 'closed');
for ($pass = 1; $pass <= 100; ++$pass) {
for ($nr = 1; $nr <= 100; ++$nr) {
if ($nr % $pass == 0) {
$doors[$nr] = $toggleState[$doors[$nr]];
}
}
}
for ($nr = 1; $nr <= 100; ++$nr)
printf("Door %d is %s\n", $nr, $doors[$nr]);
?>

[edit] PicoLisp

unoptimized

(let Doors (need 100)
(for I 100
(for (D (nth Doors I) D (cdr (nth D I)))
(set D (not (car D))) ) )
(println Doors) )

optimized

(let Doors (need 100)
(for I (sqrt 100)
(set (nth Doors (* I I)) T) )
(println Doors) )

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)

With formatting:

(let Doors (need 100)
(for I (sqrt 100)
(set (nth Doors (* I I)) T) )
(make
(for (N . D) Doors
(when D (link N)) ) ) )

Output:

(1 4 9 16 25 36 49 64 81 100)

[edit] Piet

image

[edit] Pike

array onehundreddoors()
{
array doors = allocate(100);
foreach(doors; int i;)
for(int j=i; j<100; j+=i+1)
doors[j] = !doors[j];
return doors;
}

optimized version:

array doors = map(enumerate(100,1,1), lambda(int x)
{
return sqrt((float)x)%1 == 0.0;
});
write("%{%d %d %d %d %d %d %d %d %d %d\n%}\n", doors/10)

output:

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 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1

[edit] 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;
 

[edit] PL/SQL

Unoptimized

 
DECLARE
TYPE doorsarray IS VARRAY(100) OF BOOLEAN;
doors doorsarray := doorsarray();
BEGIN
 
doors.EXTEND(100); --ACCOMMODATE 100 DOORS
 
FOR i IN 1 .. doors.COUNT --MAKE ALL 100 DOORS FALSE TO INITIALISE
LOOP
doors(i) := FALSE;
END LOOP;
 
FOR j IN 1 .. 100 --ITERATE THRU USING MOD LOGIC AND FLIP THE DOOR RIGHT OPEN OR CLOSE
LOOP
FOR k IN 1 .. 100
LOOP
IF MOD(k,j)=0 THEN
doors(k) := NOT doors(k);
END IF;
END LOOP;
END LOOP;
 
FOR l IN 1 .. doors.COUNT --PRINT THE STATUS IF ALL 100 DOORS AFTER ALL ITERATION
LOOP
DBMS_OUTPUT.PUT_LINE('DOOR '||l||' IS -->> '||CASE WHEN SYS.DBMS_SQLTCB_INTERNAL.I_CONVERT_FROM_BOOLEAN(doors(l)) = 'TRUE'
THEN 'OPEN'
ELSE 'CLOSED'
END);
END LOOP;
 
END;
 

[edit] 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

for i to 100 do
lvars root = sqrt(i);
i; if root = round(root) then ' open' ><; else ' closed' ><; endif; =>
endfor;

[edit] PostScript

Bruteforce:
/doors [ 100 { false } repeat ] def
 
1 1 100 { dup 1 sub exch 99 {
dup doors exch get not doors 3 1 roll put
} for } for
doors pstack
Shows:
[true false false true false false false false true false ...<90 doors later>... true]

[edit] PowerShell

[edit] unoptimized

$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] -bxor 1
}
}
foreach($doornum in 1..100) {
if($doors[($doornum-1)] -eq $true) {"$doornum open"}
else {"$doornum closed"}
}

[edit] Alternative Method

function Get-DoorState($NumberOfDoors)
{
begin
{
$Doors = @()
$Multiple = 1
}
 
process
{
for ($i = 1; $i -le $NumberOfDoors; $i++)
{
$Door = [pscustomobject]@{
Name = $i
Open = $false
}
 
$Doors += $Door
}
 
While ($Multiple -le $NumberOfDoors)
{
Foreach ($Door in $Doors)
{
if ($Door.name % $Multiple -eq 0)
{
If ($Door.open -eq $False){$Door.open = $True}
Else {$Door.open = $False}
}
}
 
$Multiple++
}
}
 
end {$Doors}
}

[edit] unoptimized Pipeline

$doors = 1..100 | ForEach-Object {0}
1..100 | ForEach-Object { $a=$_;1..100 | Where-Object { -not ( $_ % $a ) } | ForEach-Object { $doors[$_-1] = $doors[$_-1] -bxor 1 }; if ( $doors[$a-1] ) { "door opened" } else { "door closed" } }
 

[edit] unoptimized Pipeline 2

$doors = 1..100 | ForEach-Object {0}
$visited = 1..100
1..100 | ForEach-Object { $a=$_;$visited[0..([math]::floor(100/$a)-1)] | Where-Object { -not ( $_ % $a ) } | ForEach-Object { $doors[$_-1] = $doors[$_-1] -bxor 1;$visited[$_/$a-1]+=($_/$a) }; if ( $doors[$a-1] ) { "door opened" } else { "door closed" } }
 

[edit] unoptimized Pipeline 3 (dynamically build pipeline)

1..100|foreach-object {$pipe += "toggle $_ |"} -begin {$pipe=""}
filter toggle($pass) {$_.door = $_.door -xor !($_.index % $pass);$_}
invoke-expression "1..100| foreach-object {@{index=`$_;door=`$false}} | $pipe out-host"
 

[edit] ProDOS

Uses math module.

enableextensions 
enabledelayedexpansion
editvar /newvar /value=0 /title=closed
editvar /newvar /value=1 /title=open
editvar /newvar /range=1-100 /increment=1 /from=2
editvar /newvar /value=2 /title=next
:doors
for /alloccurrences (!next!-!102!) do editvar /modify /value=-open-
editvar /modify /value=-next-=+1
if -next- /hasvalue=100 goto :cont else goto :doors
:cont
printline !1!-!102!
stoptask

[edit] Prolog

[edit] unoptimized

doors_unoptimized(N) :-
length(L, N),
maplist(init, L),
doors(N, N, L, L1),
affiche(N, L1).
 
init(close).
 
doors(Max, 1, L, L1) :-
!,
inverse(1, 1, Max, L, L1).
 
doors(Max, N, L, L1) :-
N1 is N - 1,
doors(Max, N1, L, L2),
inverse(N, 1, Max, L2, L1).
 
 
inverse(N, Max, Max, [V], [V1]) :-
!,
0 =:= Max mod N -> inverse(V, V1); V1 = V.
 
inverse(N, M, Max, [V|T], [V1|T1]) :-
M1 is M+1,
inverse(N, M1, Max, T, T1),
( 0 =:= M mod N -> inverse(V, V1); V1 = V).
 
 
inverse(open, close).
inverse(close, open).
 
affiche(N, L) :-
forall(between(1, N, I),
( nth1(I, L, open) -> format('Door ~w is open.~n', [I]); true)).
 

[edit] optimized

doors_optimized(N) :-
Max is floor(sqrt(N)),
forall(between(1, Max, I),
( J is I*I,format('Door ~w is open.~n',[J]))).
 
 

[edit] PureBasic

unoptimized

Dim doors.i(100)
 
For x = 1 To 100
y = x
While y <= 100
doors(y) = 1 - doors(y)
y + x
Wend
Next
 
OpenConsole()
PrintN("Following Doors are open:")
For x = 1 To 100
If doors(x)
Print(Str(x) + ", ")
EndIf
Next
Input()

optimized

OpenConsole()
PrintN("Following Doors are open:")
For i = 1 To 100
root.f = Sqr(i)
If root = Int(root)
Print (Str(i) + ", ")
EndIf
Next
Input()


Output:

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

[edit] Python

Works with: Python version 2.5+

unoptimized

 
doors = [False] * 100
for i in xrange(100):
for j in xrange(i, 100, i+1):
doors[j] = not doors[j]
print "Door %d:" % (i+1), 'open' if doors[i] 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'

One liner using a list comprehension, item lookup, and is_integer

print '\n'.join(['Door %s is %s' % (i, ('closed', 'open')[(i**0.5).is_integer()]) for i in xrange(1, 101)])

One liner using a generator expression, ternary operator, and modulo

print '\n'.join('Door %s is %s' % (i, 'closed' if i**0.5 % 1 else 'open') for i in range(1, 101))
Works with: Python version 3.x
 
for i in range(1, 101):
if i**0.5 % 1:
state='open'
else:
state='close'
print("Door {}:{}".format(i, state))
 

[edit] Q

unoptimized

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

optimized

`closed`open (1+til 100) in `int$xexp[;2] 1+til 10

[edit] R

Using a loop

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()


optimized

x <- rep(1, 100)
for (i in 1:100-1) {
x <- xor(x, rep(c(rep(0,i),1), length.out=100))
}
which(!x)

Using a **ply function

doors_puzzle <- function(ndoors=100,passes=100) {
names(which(table(unlist(sapply(1:passes, function(X) seq(0, ndoors, by=X)))) %% 2 == 1))
}
 
doors_puzzle()

[edit] Racket

 
#lang racket
 
;; Applies fun to every step-th element of seq, leaving the others unchanged.
(define (map-step fun step seq)
(for/list ([elt seq] [i (in-naturals)])
((if (zero? (modulo i step)) fun values) elt)))
 
(define (toggle-nth n seq)
(map-step not n seq))
 
(define (solve seq)
(for/fold ([result seq]) ([_ seq] [pass (in-naturals 1)])
(toggle-nth pass result)))
 
(for ([door (solve (make-vector 101 #f))] [index (in-naturals)]
#:when (and door (> index 0)))
(printf "~a is open~%" index))
 

Optimized:

 
#lang racket
(for ([x (in-range 1 101)] #:when (exact-integer? (sqrt x)))
(printf "~a is open\n" x))
 

Unoptimized imperative, with graphic rendering:

 
#lang slideshow
(define-syntax-rule (vector-neg! vec pos)
(vector-set! vec pos (not (vector-ref vec pos))))
 
(define (make-doors)
(define doors (make-vector 100 #f))
(for* ([i 100] [j (in-range i 100 (add1 i))]) (vector-neg! doors j))
doors)
 
(displayln (list->string (for/list ([d (make-doors)]) (if d #\o #\-))))
 
(define closed-door (inset (filled-rectangle 4 20) 2))
(define open-door (inset (rectangle 4 20) 2))
 
(for/fold ([doors (rectangle 0 0)]) ([open? (make-doors)])
(hc-append doors (if open? open-door closed-door)))
 

Output:

100doors rkt.png

[edit] REALbasic

'True=Open; False=Closed
Dim doors(100) As Boolean 'Booleans default to false
For j As Integer = 1 To 100
For i As Integer = 1 to 100
If i Mod j = 0 Then doors(i) = Not doors(i)
Next
Next

[edit] REBOL

[edit] Unoptimized

doors: array/initial 100 'closed
repeat i 100 [
door: at doors i
forskip door i [change door either 'open = first door ['closed] ['open]]
]

[edit] Optimized

doors: array/initial 100 'closed
repeat i 10 [doors/(i * i): 'open]
 

[edit] Retro

: squared ( n-n  ) dup * ;
: doors ( n- ) [ 1 repeat 2over squared > 0; drop dup squared putn space 1+ again ] do 2drop ;
100 doors

[edit] REXX

[edit] version 1

/*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
 

[edit] version 2, the hard way

Here is another version, solving it the hard way.

/*REXX program to solve the 100 door puzzle, the hard-way version.  */
parse arg doors . /*get the first argument (# of doors.) */
if doors=='' then doors=100 /*not specified? Then assume 100 doors*/
/* 0 = closed. */
/* 1 = open. */
door.=0 /*assume all that all doors are closed.*/
 
do j=1 for doors /*process a pass-through for all doors.*/
do k=j by j to doors /* ... every Jth door from this point. */
door.k=\door.k /*toggle the "openness" of the door. */
end /*k*/
end /*j*/
say
say 'After' doors "passes, the following doors are open:"
say
do n=1 for doors
if door.n then say right(n,20)
end /*n*/

output using the default input

After 100 passes, the following doors are open:

                   1
                   4
                   9
                  16
                  25
                  36
                  49
                  64
                  81
                 100

[edit] version 3, the easy way

Here is another version, solving it the easy way.

/*REXX program to solve the 100 door puzzle, the easy-way version.  */
parse arg doors . /*get the first argument (# of doors.) */
if doors=='' then doors=100 /*not specified? Then assume 100 doors*/
/* 0 = closed. */
/* 1 = open. */
door.=0 /*assume all that all doors are closed.*/
say
say 'For the' doors "doors problem, the following doors are open:"
say
do j=1 for doors /*process an easy pass-through. */
p=j**2 /*square the door number. */
if p>doors then leave /*if too large, we're done. */
say right(p,20)
end /*j*/

output

For the 100 doors problem, the following doors are open:

                   1
                   4
                   9
                  16
                  25
                  36
                  49
                  64
                  81
                 100

[edit] version 4, easy way, 1,000 doors

Here's another easy-way solution (version 2), but for 1,000 doors.

/*REXX program to solve the 100 door puzzle, the easy-way version 2.*/
parse arg doors . /*get the first argument (# of doors.) */
if doors=='' then doors=1000 /*not specified? Then assume 1000 doors*/
/* 0 = closed. */
/* 1 = open. */
door.=0 /*assume all that all doors are closed.*/
say
say 'For the' doors "doors problem, the open doors are:"
say
do j=1 for doors while j**2<=doors /*limit pass-throughs.*/
say right(j**2,20)
end /*j*/

output

For the 1000 doors problem, the open doors are:

                   1
                   4
                   9
                  16
                  25
                  36
                  49
                  64
                  81
                 100
                 121
                 144
                 169
                 196
                 225
                 256
                 289
                 324
                 361
                 400
                 441
                 484
                 529
                 576
                 625
                 676
                 729
                 784
                 841
                 900
                 961

[edit] Ruby

unoptimized; Ruby-way

class Door
attr_reader :state
 
def initialize
@state = :closed
end
 
def close
@state = :closed
end
 
def open
@state = :open
end
 
def closed?
@state == :closed
end
 
def open?
@state == :open
end
 
def toggle
if closed? then open else close end
end
 
def to_s
@state.to_s
end
end
 
doors = Array.new(100) { Door.new }
1.upto(100) do |multiplier|
doors.each_with_index do |door, i|
door.toggle if (i + 1) % multiplier == 0
end
end
 
doors.each_with_index { |door, i| puts "Door #{i+1} is #{door}." }

unoptimized

n = 100
Open = "open"
Closed = "closed"
def Open.toggle
Closed
end
def Closed.toggle
Open
end
doors = [Closed] * (n + 1)
for mul in 1..n
for x in (mul..n).step(mul)
doors[x] = doors[x].toggle
end
end
doors.each_with_index do |b, i|
puts "Door #{i} is #{b}" if i > 0
end

optimized

n = 100
(1..n).each do |i|
puts "Door #{i} is #{i**0.5 == (i**0.5).round ? "open" : "closed"}"
end

generic true/false, with another way of handling the inner loop demonstrating Range#step

doors = [false] * 100
100.times do |i|
(i ... doors.length).step(i + 1) do |j|
doors[j] = !doors[j]
end
end
puts doors.map.with_index(1){|d,i| "Door #{i} is #{d ? 'open' : 'closed'}."}
Output:
Door 1 is open
Door 2 is closed
Door 3 is closed
Door 4 is open
Door 5 is closed
Door 6 is closed
Door 7 is closed
Door 8 is closed
Door 9 is open
Door 10 is closed
Door 11 is closed
Door 12 is closed
Door 13 is closed
Door 14 is closed
Door 15 is closed
Door 16 is open
Door 17 is closed
Door 18 is closed
Door 19 is closed
Door 20 is closed
Door 21 is closed
Door 22 is closed
Door 23 is closed
Door 24 is closed
Door 25 is open
Door 26 is closed
Door 27 is closed
Door 28 is closed
Door 29 is closed
Door 30 is closed
Door 31 is closed
Door 32 is closed
Door 33 is closed
Door 34 is closed
Door 35 is closed
Door 36 is open
Door 37 is closed
Door 38 is closed
Door 39 is closed
Door 40 is closed
Door 41 is closed
Door 42 is closed
Door 43 is closed
Door 44 is closed
Door 45 is closed
Door 46 is closed
Door 47 is closed
Door 48 is closed
Door 49 is open
Door 50 is closed
Door 51 is closed
Door 52 is closed
Door 53 is closed
Door 54 is closed
Door 55 is closed
Door 56 is closed
Door 57 is closed
Door 58 is closed
Door 59 is closed
Door 60 is closed
Door 61 is closed
Door 62 is closed
Door 63 is closed
Door 64 is open
Door 65 is closed
Door 66 is closed
Door 67 is closed
Door 68 is closed
Door 69 is closed
Door 70 is closed
Door 71 is closed
Door 72 is closed
Door 73 is closed
Door 74 is closed
Door 75 is closed
Door 76 is closed
Door 77 is closed
Door 78 is closed
Door 79 is closed
Door 80 is closed
Door 81 is open
Door 82 is closed
Door 83 is closed
Door 84 is closed
Door 85 is closed
Door 86 is closed
Door 87 is closed
Door 88 is closed
Door 89 is closed
Door 90 is closed
Door 91 is closed
Door 92 is closed
Door 93 is closed
Door 94 is closed
Door 95 is closed
Door 96 is closed
Door 97 is closed
Door 98 is closed
Door 99 is closed
Door 100 is open

[edit] Run BASIC

dim doors(100)
print "Open doors ";
for i = 1 to 100
for door = i to 100 step i
doors(door) = (doors(door) <> 1)
if i = door and doors(door) = 1 then print i;" ";
next door
next i
Output:
Open doors 1 4 9 16 25 36 49 64 81 100

[edit] Rust

// rust 0.8
 
fn main() {
let mut door_open = [false, ..100];
 
for pass in std::iter::range_inclusive(1, 100) {
for door in std::iter::range_inclusive(1, 100) {
if door % pass == 0 {
door_open[door - 1] = !door_open[door - 1];
}
}
}
for (i, state) in door_open.iter().enumerate() {
println!("Door {} is {}.", i + 1,
if *state {"open"} else {"closed"});
}
}

Port of the Ruby optimized version:

// rust 0.8
 
fn main() {
for i in std::iter::range_inclusive(1,100) {
let x = (i as f64).pow(&0.5);
let state = if x == x.round() {"open"} else {"closed"};
println!("Door {} is {}", i, state);
}
}

[edit] S-lang

variable door,
isOpen = Char_Type [101],
pass;
 
for (door = 1; door <= 100; door++) {
isOpen[door] = 0;
}
 
for (pass = 1; pass <= 100; pass++) {
for (door = pass; door <= 100; door += pass) {
isOpen[door] = not isOpen[door];
}
}
 
for (door = 1; door <= 100; door++) {
if (isOpen[door]) {
print("Door " + string(door) + ":open");
} else {
print("Door " + string(door) + ":close");
}
}

[edit] Salmon

Here's an unoptimized version:

variable open := <<(* --> false)>>;
for (pass; 1; pass <= 100)
for (door_num; pass; door_num <= 100; pass)
open[door_num] := !(open[door_num]);;;
iterate (door_num; [1...100])
print("Door ", door_num, " is ",
(open[door_num] ? "open.\n" : "closed.\n"));;

And here's an optimized one-line version:

iterate (x; [1...10]) { iterate (y; [(x-1)*(x-1)+1...x*x-1]) { print("Door ", y, " is closed.\n"); }; print("Door ", x*x, " is open.\n"); };

And a shorter optimized one-line version:

variable y:=1;for(x;1;x<101)"Door "~sprint(x)~" is "~(x==y*y?{++y;return"open";}:"closed")!;

[edit] SAS

data _null_;
open=1;
close=0;
array Door{100};
do Pass = 1 to 100;
do Current = Pass 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;

[edit] Scala

for { i <- 1 to 100
r = 1 to 100 map (i % _ == 0) reduceLeft (_^_)
} println (i +" "+ (if (r) "open" else "closed"))

The map operation maps each door (i) to a boolean sequence of toggles, one for each pass: true toggles, false leaves the same.

The reduceLeft method combines all the toggles sequentially, using the XOR operator.

And then we just need to output the result.


I made a version that optional accepts an argument for the number of doors. It is also a little more a ‘classical’ solution:

 
def openDoors(length : Int = 100) = {
var isDoorOpen = new Array[Boolean](length)
 
for (i <- 0 until length) {
for (j <- i until length by i + 1) {
isDoorOpen(j) ^= true
}
}
isDoorOpen
}
 
val doorState = scala.collection.immutable.Map(false -> "closed", true -> "open")
val isDoorOpen = openDoors()
 
for (doorNo <- 0 until isDoorOpen.length) {
println("Door %d is %s".format(doorNo + 1, doorState(isDoorOpen(doorNo))))
}
 

I created the function openDoors which gives back an array signifying if a door is open and optional accepts an argument for the number of doors. (I like to make things general.) I call the function and use the result to display the status of the doors.


"Optimized" version:

val o = 1 to 10 map (i => i * i)
println("open: " + o)
println("closed: " + (1 to 100 filterNot o.contains))

[edit] 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;

[edit] 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)))

[edit] Seed7

unoptimized

$ include "seed7_05.s7i";
 
const proc: main is func
local
var array boolean: doorOpen is 100 times FALSE;
var integer: pass is 0;
var integer: index is 0;
var array[boolean] string: closedOrOpen is [boolean] ("closed", "open");
begin
for pass range 1 to 100 do
for key index range doorOpen do
if index rem pass = 0 then
doorOpen[index] := not doorOpen[index];
end if;
end for;
end for;
for key index range doorOpen do
write(index lpad 3 <& " is " <& closedOrOpen[doorOpen[index]] rpad 7);
if index rem 5 = 0 then
writeln;
end if;
end for;
end func;

optimized

$ include "seed7_05.s7i";
 
const proc: main is func
local
var integer: index is 0;
var integer: number is 0;
var array[boolean] string: closedOrOpen is [boolean] ("closed", "open");
begin
for index range 1 to 100 do
number := sqrt(index);
write(index lpad 3 <& " is " <& closedOrOpen[number**2 = index] rpad 7);
if index rem 5 = 0 then
writeln;
end if;
end for;
end func;

Output of both programs:

  1 is open     2 is closed   3 is closed   4 is open     5 is closed 
  6 is closed   7 is closed   8 is closed   9 is open    10 is closed 
 11 is closed  12 is closed  13 is closed  14 is closed  15 is closed 
 16 is open    17 is closed  18 is closed  19 is closed  20 is closed 
 21 is closed  22 is closed  23 is closed  24 is closed  25 is open   
 26 is closed  27 is closed  28 is closed  29 is closed  30 is closed 
 31 is closed  32 is closed  33 is closed  34 is closed  35 is closed 
 36 is open    37 is closed  38 is closed  39 is closed  40 is closed 
 41 is closed  42 is closed  43 is closed  44 is closed  45 is closed 
 46 is closed  47 is closed  48 is closed  49 is open    50 is closed 
 51 is closed  52 is closed  53 is closed  54 is closed  55 is closed 
 56 is closed  57 is closed  58 is closed  59 is closed  60 is closed 
 61 is closed  62 is closed  63 is closed  64 is open    65 is closed 
 66 is closed  67 is closed  68 is closed  69 is closed  70 is closed 
 71 is closed  72 is closed  73 is closed  74 is closed  75 is closed 
 76 is closed  77 is closed  78 is closed  79 is closed  80 is closed 
 81 is open    82 is closed  83 is closed  84 is closed  85 is closed 
 86 is closed  87 is closed  88 is closed  89 is closed  90 is closed 
 91 is closed  92 is closed  93 is closed  94 is closed  95 is closed 
 96 is closed  97 is closed  98 is closed  99 is closed 100 is open   

[edit] SETL

Unoptimized

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;

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.

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;

[edit] Sidef

Unoptimized

var doors = [];
 
{ |pass|
{ |i|
i %% pass && (
doors[i] := false -> not!
);
} * 100;
} * 100;
 
{ |i|
"Door %3d is %s\n".printf(i, doors[i] ? 'open' : 'closed');
} * 100;

Optimized

{ |i|
"Door %3d is %s\n".printf(i, ["closed", "open"][i**0.5->isInt]);
} * 100;

[edit] Slate

Unoptimized

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'])].

Optimized

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'])].

[edit] Smalltalk

Works with: GNU Smalltalk

Unoptimized

|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
]

Optimized

|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
]
Works with: Squeak Smalltalk

Unoptimized, using Morphs

 
| 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.
 

[edit] SNOBOL4

unoptimized

 
DEFINE('PASS(A,I),O') :(PASS.END)
PASS O = 0
PASS.LOOP O = O + I
EQ(A<O>,1) :S(PASS.1)F(PASS.0)
PASS.0 A<O> = 1 :S(PASS.LOOP)F(RETURN)
PASS.1 A<O> = 0 :S(PASS.LOOP)F(RETURN)
PASS.END
 
MAIN D = ARRAY(100,0)
I = 0
 
MAIN.LOOP I = LE(I,100) I + 1 :F(OUTPUT)
PASS(D,I) :(MAIN.LOOP)
 
OUTPUT I = 1 ; OPEN = 'Opened doors are: '
OUTPUT.LOOP OPEN = OPEN EQ(D<I>,1) " " I
I = LE(I,100) I + 1 :S(OUTPUT.LOOP)F(OUTPUT.WRITE)
OUTPUT.WRITE OUTPUT = OPEN
 
END
 

A run of this using CSNOBOL4 looks like this:

$ snobol4 100doors.sno 
The Macro Implementation of SNOBOL4 in C (CSNOBOL4) Version 1.3+
    by Philip L. Budne, January 23, 2011
SNOBOL4 (Version 3.11, May 19, 1975)
    Bell Telephone Laboratories, Incorporated

No errors detected in source program

Opened doors are:  1 4 9 16 25 36 49 64 81 100
Normal termination at level 0
100doors.sno:18: Last statement executed was 19

(There are command flags to remove the header and the summary, but these have been left in to keep the original SNOBOL4 experience intact.)

optimized

 
MAIN D = ARRAY(100,0)
I = 1
 
MAIN.LOOP LE(I, 10) :F(OUTPUT)
D<I ** 2> = 1
I = I + 1 :(MAIN.LOOP)
 
OUTPUT I = 1 ; O = 'Opened doors are: '
OUTPUT.LOOP O = O EQ(D<I>,1) " " I
I = LE(I,100) I + 1 :S(OUTPUT.LOOP)F(OUTPUT.WRITE)
OUTPUT.WRITE OUTPUT = O
END
 

The output of this version is almost identical to the above.

[edit] Sparkling

unoptimized

/* declare the variables */
var isOpen = {};
var pass, door;
 
/* initialize the doors */
for door = 0; door < 100; door++ {
isOpen[door] = true;
}
 
/* do the 99 remaining passes */
for pass = 1; pass < 100; ++pass {
for door = pass; door < 100; door += pass+1 {
isOpen[door] = !isOpen[door];
}
}
 
/* print the results */
var states = { true: "open", false: "closed" };
for door = 0; door < 100; door++ {
printf("Door #%d is %s.\n", door+1, states[isOpen[door]]);
}

optimized

/* declare the variables */
var door_sqrt = 1;
var door;
 
/* print the perfect square doors as open */
for door = 0; door < 100; door++ {
if (door_sqrt*door_sqrt == door+1) {
printf("Door #%d is open.\n", door+1);
door_sqrt ++;
} else {
printf("Door #%d is closed.\n", door+1);
}
}

[edit] Tcl

unoptimized

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"}]]
}

optimized

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]]
}

graphical

Library: Tk

Inspired by the E solution, here's a visual representation

package require Tcl 8.5
package require Tk
 
array set door_status {}
 
# 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
}
}
 
# 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
}
}
}
}

[edit] TI-83 BASIC

[edit] Unoptimized

PROGRAM:DOORS100
:ClrHome
:Disp "SETTING UP LIST"
:Disp "PLEASE WAIT..."
:For(I,1,100,1)
:0→L1(I)
:End
:ClrHome
:Disp "Pass"
:For(I,1,100,1)
:For(J,I,100,I)
:Output(2,1,I)
:not(L1(J))→L1(J)
:End
:End
:ClrHome
 

[edit] Optimized

PROGRAM:DOORSOPT
:For(I,1,100,1)
:not(fPart(√(I)))→L1(I)
:End
 


[edit] TI-89 BASIC

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

[edit] TorqueScript

for(%steps = 1; %a <= 100; %a++)
for(%current = %steps; %current <= 100; %current += %steps)
%door[%current] = !%door[%current];
for(%a = 1; %a <= 100; %a++)
echo("Door #" @ %a @ " is" SPC %door[%current] ? "Open" : "Closed" @ ".");

[edit] TSE SAL

 
 
// library: math: get: task: door: open: close100 <description></description> <version control></version control> <version>1.0.0.0.11</version> <version control></version control> (filenamemacro=getmaocl.s) [<Program>] [<Research>] [kn, ri, mo, 31-12-2012 22:03:16]
PROC PROCMathGetTaskDoorOpenClose( INTEGER doorMaxI, INTEGER passMaxI )
// e.g. PROC Main()
// e.g. PROCMathGetTaskDoorOpenClose( 100, 100 )
// e.g. END
// e.g.
// e.g. <F12> Main()
//
// ===
//
// The output will be:
//
// 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
//
// ===
//
INTEGER passMinI = 1
INTEGER passI = 0
//
INTEGER doorminI = 1
INTEGER doorI = 0
//
STRING s[255] = ""
//
INTEGER bufferI = 0
//
PushPosition()
bufferI = CreateTempBuffer()
PopPosition()
//
FOR doorI = doorMinI TO doorMaxI
//
SetGlobalInt( Format( "doorsI", doorI ), 0 )
//
ENDFOR
//
FOR passI = passMinI TO passMaxI
//
doorI = passI - passI
//
REPEAT
//
doorI = doorI + passI
//
SetGlobalInt( Format( "doorsI", doorI ), NOT( GetGlobalInt( Format( "doorsI", doorI ) ) ) )
//
UNTIL ( doorI >= doorMaxI )
//
ENDFOR
//
FOR doorI = doorMinI TO doorMaxI
//
IF ( GetGlobalInt( Format( "doorsI", doorI ) ) > 0 )
//
s = "open"
//
AddLine( Format( "door", " ", doorI, " ", "is", " ", s ), bufferI )
//
ELSE
//
s = "closed"
//
ENDIF
//
ENDFOR
//
AddLine( "all other doors are closed", bufferI )
//
GotoBufferId( bufferI )
//
END
 
PROC Main()
PROCMathGetTaskDoorOpenClose( 100, 100 )
END
 
 


[edit] TUSCRIPT

 
$$ MODE TUSCRIPT
DICT doors create
COMPILE
LOOP door=1,100
LOOP pass=1,100
SET go=MOD (door,pass)
DICT doors lookup door,num,cnt,status
IF (num==0) THEN
SET status="open"
DICT doors add door,num,cnt,status
ELSE
IF (go==0) THEN
IF (status=="closed") THEN
SET status="open"
ELSE
SET status="closed"
ENDIF
DICT doors update door,num,cnt,status
ENDIF
ENDIF
ENDLOOP
ENDLOOP
ENDCOMPILE
DICT doors unload door,num,cnt,status
 

Output (variable status):

 status       = *
           1 = open
           2 = closed
           3 = closed
           4 = open
           5 = closed
           6 = closed
           7 = closed
           8 = closed
           9 = open
          10 = closed
          11 = closed
          12 = closed
          13 = closed
          14 = closed
          15 = closed
          16 = open
          17 = closed
          18 = closed
          19 = closed
          20 = closed
          21 = closed
          22 = closed
          23 = closed
          24 = closed
          25 = open
          26 = closed
          27 = closed
          28 = closed
          29 = closed
          30 = closed
          31 = closed
          32 = closed
          33 = closed
          34 = closed
          35 = closed
          36 = open
          37 = closed
          38 = closed
          39 = closed
          40 = closed
          41 = closed
          42 = closed
          43 = closed
          44 = closed
          45 = closed
          46 = closed
          47 = closed
          48 = closed
          49 = open
          50 = closed
          51 = closed
          52 = closed
          53 = closed
          54 = closed
          55 = closed
          56 = closed
          57 = closed
          58 = closed
          59 = closed
          60 = closed
          61 = closed
          62 = closed
          63 = closed
          64 = open
          65 = closed
          66 = closed
          67 = closed
          68 = closed
          69 = closed
          70 = closed
          71 = closed
          72 = closed
          73 = closed
          74 = closed
          75 = closed
          76 = closed
          77 = closed
          78 = closed
          79 = closed
          80 = closed
          81 = open
          82 = closed
          83 = closed
          84 = closed
          85 = closed
          86 = closed
          87 = closed
          88 = closed
          89 = closed
          90 = closed
          91 = closed
          92 = closed
          93 = closed
          94 = closed
          95 = closed
          96 = closed
          97 = closed
          98 = closed
          99 = closed
         100 = open

[edit] TXR

@(do (defun hyaku-mai-to ()
(let ((doors (vector 100)))
(each ((i (range 0 99)))
(each ((j (range i 99 (+ i 1))))
(flip [doors j])))
doors))
(each ((counter (range 1))
(door (hyaku-mai-to)))
(put-line `door @counter is @(if door "open" "closed")`)))

[edit] UNIX Shell

Works with: Bourne Again SHell
#! /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

Optimised version

#!/bin/bash
 
for i in {1..100}; do
door[$i*$i]=1
[ -z ${door[$i]} ] && echo "$i closed" || echo "$i open"
done

[edit] 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.

#import std
#import nat
 
doors = 0!* iota 100
 
pass("n","d") = remainder\"n"?l(~&r,not ~&r)* num "d"
 
#cast %nL
 
main = ~&rFlS num pass=>doors nrange(100,1)

optimized version:

#import nat
 
#cast %nL
 
main = product*tiiXS iota10

output:

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

[edit] Vala

Unoptimized

int main() {
bool doors_open[101];
for(int i = 1; i < doors_open.length; i++) {
for(int j = 1; i*j < doors_open.length; j++) {
doors_open[i*j] = !doors_open[i*j];
}
stdout.printf("%d: %s\n", i, (doors_open[i] ? "open" : "closed"));
}
return 0;
}

Output:

1: open
2: closed
3: closed
4: open
5: closed
6: closed
7: closed
8: closed
9: open
10: closed
11: closed
...

Optimized

int main() {
int i = 1;
while(i*i <= 100) {
stdout.printf("${i*i} open\n");
i++;
}
return 0;
}

Output:

1 open
4 open
9 open
16 open
25 open
36 open
49 open
64 open
81 open
100 open

[edit] VBA

 
Sub Rosetta_100Doors()
Dim Door(100) As Boolean, i As Integer, j As Integer
For i = 1 To 100 Step 1
For j = i To 100 Step i
Door(j) = Not Door(j)
Next j
If Door(i) = True Then
Debug.Print "Door " & i & " is Open"
Else
Debug.Print "Door " & i & " is Closed"
End If
Next i
End Sub
 

[edit] VBScript

Works with: Windows Script Host version 5.7

Unoptimized

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

[edit] 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'.

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'
}
}

Optimized

Buf_Switch(Buf_Free)
Ins_Char('-', COUNT, 100)
for (#1=1; #1 <= 10; #1++) {
Goto_Col(#1*#1)
Ins_Char('O', OVERWRITE)
}

Output:

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

[edit] VHDL

unoptimized

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity DOORS is
port (CLK: in std_logic; OUTPUT: out std_logic_vector(1 to 100));
end DOORS;
 
architecture Behavioral of DOORS is
begin
process (CLK)
variable TEMP: std_logic_vector(1 to 100);
begin
--setup closed doors
TEMP := (others => '0');
 
--looping through
for i in 1 to TEMP'length loop
for j in i to TEMP'length loop
if (j mod i) = 0 then
TEMP(j) := not TEMP(j);
end if;
end loop;
end loop;
 
--assign output
OUTPUT <= TEMP;
end process;
end Behavioral;
 

unoptimized and synthesizable

LIBRARY ieee;
USE ieee.std_logic_1164.all;
 
 
entity doors is
port (
clk : in std_logic;
reset : in std_logic;
door : buffer std_logic_vector(1 to 100)
);
end entity doors;
 
 
architecture rtl of doors is
signal step : integer range 1 to 101;
signal addr : integer range 1 to 201;
begin
proc_step: process(clk, reset)
begin
if reset = '1' then
step <= 1;
addr <= 1;
door <= (others => '0');
elsif rising_edge(clk) then
if addr <= 100 then
door(addr) <= not door(addr);
addr <= addr + step;
elsif step <= 100 then
addr <= step + 1;
step <= step + 1;
end if;
end if;
end process;
end;
The synthesis requires 116 FFs plus combinatorial logic.

The result is stable after 581 clock cycles.

[edit] Visual Basic .NET

Works with: Visual Basic .NET 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

[edit] Wart

def (doors n)
let door (table)
for step 1 (step <= n) ++step
for j 0 (j < n) (j <- j+step)
zap! not door.j
 
for j 0 (j < n) ++j
when door.j
pr j
pr " "

[edit] Wortel

Translation of: JavaScript
; unoptimized
+^[
@var doors []
 
@for i rangei [1 100]
@for j rangei [i 100 i]
 :!@not `j doors
 
@for i rangei [1 100]
@if `i doors
 !console.log "door {i} is open"
]
; optimized, map square over 1 to 10
!*^@sq @to 10

[edit] Wrapl

Unoptimized

MOD Doors;
 
IMP Agg.Table;
IMP Std.String;
IMP IO.Terminal USE Out;
 
VAR door <- {}; EVERY door[1:to(100), "closed"];
 
DEF toggle(num) door[num] <- door[num] = "open" => "closed" // "open";
 
EVERY WITH pass <- 1:to(100), num <- pass:to(100, pass) DO toggle(num);
 
Out:write('Doors {door @ String.T}.');
 
END Doors.

Optimized

MOD Doors;
 
IMP IO.Terminal USE Out;
 
DEF open <- ALL 1:to(100) ^ 2 \ $ <= 100;
DEF closed <- ALL 1:to(100) \ NOT $ IN open;
 
Out:write('Doors {open} are open.\n');
Out:write('Doors {closed} are closed.\n');
 
END Doors.

[edit] XPL0

include c:\cxpl\codes;          \intrinsic 'code' declarations
int Door(100); \You have 100 doors in a row
define Open, Closed;
int D, Pass, Step;
 
[for D:= 0 to 100-1 do \that are all initially closed
Door(D):= Closed;
 
Step:= 1; \The first time through, you visit every door
for Pass:= 1 to 100 do \You make 100 passes by the doors
[D:= Step-1;
repeat \if the door is closed, you open it; if it is open, you close it
if Door(D)=Closed then Door(D):= Open else Door(D):= Closed;
D:= D+Step;
until D>=100;
Step:= Step+1; \The second time you only visit every 2nd door
]; \The third time, every 3rd door
\until you only visit the 100th door
\What state are the doors in after the last pass?
Text(0, "Open: "); \Which are open?
for D:= 0 to 100-1 do
if Door(D)=Open then [IntOut(0, D+1); ChOut(0,^ )];
CrLf(0);
 
Text(0, "Closed: "); \Which are closed?
for D:= 0 to 100-1 do
if Door(D)=Closed then [IntOut(0, D+1); ChOut(0,^ )];
CrLf(0);
 
\Optimized: The only doors that remain open are those that are perfect squares
Text(0, "Open: ");
D:= 1;
repeat IntOut(0, D*D); ChOut(0,^ );
D:= D+1;
until D*D>100;
CrLf(0);
]

[edit] XSLT 1.0

With input document ...

<hallway>
<door number="1">closed</door>
<door number="2">closed</door>
<door number="3">closed</door>
<door number="4">closed</door>
... etc ...
<door number="100">closed</door>
<hallway>

... visually representing the initial state of the hallway, apply the following XSLT 1.0 style-sheet...

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="xsl exsl">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
 
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="door" />
</xsl:copy>
</xsl:template>
 
<xsl:template match="door">
<xsl:variable name="door-num" select="@number" />
<xsl:variable name="knocks">
<xsl:for-each select="/*/door">
<xsl:if test="$door-num mod position() = 0">
<xsl:text>!</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<door number="{$door-num}">
<xsl:choose>
<xsl:when test="string-length($knocks) mod 2 = 1">
<xsl:text>open</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>closed</xsl:text>
</xsl:otherwise>
</xsl:choose>
</door>
</xsl:template>
 
</xsl:stylesheet>

Also see: 100 doors/XSLT

[edit] XSLT 2.0

This XSLT 2.0 style-sheet does not use the input document.

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
 
<xsl:template match="/">
<hallway>
<xsl:for-each select="1 to 100">
<xsl:variable name="door-num" select="position()" />
<door number="{$door-num}">
<xsl:value-of select="('closed','open')[
number( sum( for $pass in 1 to 100 return
number(($door-num mod $pass) = 0)) mod 2 = 1) + 1]" />

</door>
</xsl:for-each>
</hallway>
</xsl:template>
 
</xsl:stylesheet>

[edit] Yorick

Unoptimized, iterative

doors = array(0, 100);
for(i = 1; i <= 100; i++)
for(j = i; j <= 100; j += i)
doors(j) ~= 1;
print, where(doors);

Unoptimized, vectorized

doors = array(0, 100);
for(i = 1; i <= 100; i++)
doors(i::i) ~= 1;
print, where(doors);

Optimized

print, indgen(1:long(sqrt(100)))^2

All of the above output:

[1,4,9,16,25,36,49,64,81,100]

[edit] ZED

(100doors)
comment: returns the first 100 doors after making 100 passes
(always)
(pr) (first) 100 (passes) 1 (doors)
 
(doors)
comment: start with an infinite list of closed doors
(always)
(c) "'closed" (doors)
 
(passes) count doors
comment: count is greater than 100 -> make 100 passes
(>) count 100
doors
 
(passes) count doors
comment: count is not greater than 100 -> make 100 passes
(always)
(passes) (add1) count
(pass) count doors
 
(pass) count doors
comment: takes a count and a list of doors -> makes a pass over the doors
(always)
(ZEDpass) count count doors
 
(ZEDpass) count1 count2 doors
comment: count2 is one -> completes a pass over the doors
(=) count2 1
(c) (toggle) (1) doors
(pass) count1 (!) doors
 
(ZEDpass) count1 count2 doors
comment: count2 is greater than one -> completes a pass over the doors
(>) count2 1
(c) (1) doors
(ZEDpass) count1 (sub1) count2 (!) doors
 
(toggle) door
comment: door is closed -> toggles it
(=) door "'closed"
"'open"
 
(toggle) door
comment: door is open -> toggles it
(=) door "'open"
"'closed"
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox