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.
[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
optimized (Largely inspired by the optimized C implementation)
;assume all memory is initially set to 0
inc $1 ;start out with a delta of 1
openloop: inc $200,X ;open a door at X
inc $1 ;add 2 to delta
inc $1
txa ;add delta to X
adc $1
tax
cpx #$65 ;check to see if we're at the 100th door
bmi openloop ;jump back to openloop if less than 100
[edit] 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
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
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
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:
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] Axiom
Unoptimized:(open,closed,change,open?) := (true,false,not,test);Optimized:
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]
[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
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
[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%) EOR= TRUE
NEXT door%
NEXT pass%
FOR door% = 1 TO 100
IF doors%(door%) PRINT "Door " ; door% " is open"
NEXT door%
[edit] Befunge
108p0>:18p;;>:9g!18g9p08g]
*`!0\|+relet|-1`*aap81::+]
;::+1<r]!g9;>$08g1+:08paa[
*`#@_^._aa
[edit] BlitzMax
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] C
[edit] unoptimized
#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;
}
[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
.
#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>Or really optimize it -- square of an integer is, well, computable:
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;
}
#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++
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
.
#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"));
}
}
[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)
:while (< i 100)]
(aset doors i (not (aget doors i))))
doors))
(defn open-doors [] (for [[d n] (map vector (doors) (iterate inc 1)) :when d] n))
(defn print-open-doors []
(println
"Open doors after 100 passes:"
(apply str (interpose ", " (open-doors)))))
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)
:while (< i 100)]
i)))
(defn open-doors [] (for [[d n] (map vector (doors) (iterate inc 1)) :when d] n))
(defn print-open-doors []
(println
"Open doors after 100 passes:"
(apply str (interpose ", " (open-doors)))))
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 PIC 9(3) VALUE ZEROES.
01 StepSize PIC 9(3) VALUE ZEROES.
01 DoorTable.
02 Doors PIC 9(1) OCCURS 100 TIMES.
01 Idx PIC 9(3).
PROCEDURE DIVISION.
Begin.
MOVE 1 TO StepSize
PERFORM 100 TIMES
MOVE StepSize TO Current
PERFORM UNTIL Current > 100
SUBTRACT Doors(Current) FROM 1 GIVING Doors(Current)
ADD StepSize TO Current GIVING Current
END-PERFORM
ADD 1 TO StepSize GIVING StepSize
END-PERFORM
PERFORM VARYING Idx FROM 1 BY 1
UNTIL Idx > 100
IF Doors(Idx) = 0
DISPLAY Idx " is closed."
ELSE
DISPLAY Idx " is open."
END-IF
END-PERFORM
STOP RUN.
[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 (eq (nth n d) value1)
(setf (nth n d) value2)
(setf (nth n d) value1))
d))
(defun visit-every (doors num iter value1 value2)
"visits every 'num' door in the list"
(if (> (* iter num) (length doors))
doors
(visit-every (visit-door doors (* num iter) value1 value2)
num
(+ 1 iter)
value1
value2)))
(defun do-all-visits (doors cnt value1 value2)
"Visits all doors changing the values accordingly"
(if (< cnt 1)
doors
(do-all-visits (visit-every doors cnt 1 value1 value2)
(- cnt 1)
value1
value2)))
(defun print-doors (doors)
"Pretty prints the doors list"
(format T "~{~A ~A ~A ~A ~A ~A ~A ~A ~A ~A~%~}~%" doors))
(defun start (&optional (size 100))
"Start the program"
(let* ((open "_")
(shut "#")
(doors (make-list size :initial-element shut)))
(print-doors (do-all-visits doors size open shut))))
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] D
import std.stdio;
enum DoorState { Closed, Open }
alias DoorState[] Doors;
Doors flipUnoptimized(Doors doors) {
doors[] = DoorState.Closed;
foreach (i; 0 .. doors.length)
for (int j = i; j < doors.length; j += i+1)
if (doors[j] == DoorState.Open)
doors[j] = DoorState.Closed;
else
doors[j] = DoorState.Open;
return doors;
}
Doors flipOptimized(Doors doors) {
doors[] = DoorState.Closed;
for (int i = 1; i*i <= doors.length; i++)
doors[i*i - 1] = DoorState.Open;
return doors;
}
// test program
void main() {
auto doors = new Doors(100);
foreach (i, door; flipUnoptimized(doors))
if (door == DoorState.Open)
write(i+1, " ");
writeln();
foreach (i, door; flipOptimized(doors))
if (door == DoorState.Open)
write(i+1, " ");
writeln();
}
- Output:
1 4 9 16 25 36 49 64 81 100 1 4 9 16 25 36 49 64 81 100
[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] Delphi
- See Pascal
[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
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] 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
Result := create {LINKED_LIST [DOOR]}.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
-- Represents a 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
let gate (x::xs) (y::ys) | x == y = Open :: gate xs ys
gate (x::xs) ys = Closed :: gate xs ys
gate [] _ = []
let run n = gate [1..n] [& k*k \\ k <- [1..]]
Alternate Approach
open Core
let run n = takeWhile (<n) [& k*k \\ k <- [1..]]
[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
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 step 1
$ for j=i to 100 step i
$ if doors[j]==0 then doors[j]:=1;
$ else doors[j]:=0;
$ endif;
$ end;
$ end;
$ return doors
$endfunction
A:=Doors;
for i=1 to 100 step 1; if A[i]==1 then "door "|i|" is open" endif; 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] 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
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 ;
[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] 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
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] 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] 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)
{
neko.Lib.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
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
for(i,1,100, doors append(false))
for(i,1,100,
for(x,i,100, i, doors atPut(x - 1, doors at(x - 1) not))
)
doors foreach(i, x, if(x, "Door #{i + 1} is open" interpolate println))
[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");
}
}
}
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
var doors = [], n = 100, i, j;
for (i = 1; i <= n; i++) {
for (j = i; j <= n; j += i) {
doors[j] = !doors[j];
}
}
for (i = 1 ; i <= n ; i++) {
if (doors[i]) console.log("Door " + i + " is open");
}
outputs
door 1 is open. door 4 is open. door 9 is open. door 16 is open. door 25 is open. door 36 is open. door 49 is open. door 64 is open. door 81 is open. door 100 is open.Using features of JavaScript 1.6, this
var
n = 100,
doors = [n],
step,
idx;
// now, start opening and closing
for (step = 1; step <= n; step += 1)
for (idx = step; idx <= n; idx += step)
// toggle state of door
doors[idx] = !doors[idx];
// find out which doors are open
var open = doors.reduce(function(open, val, idx) {
if (val) {
open.push(idx);
}
return open;
}, []);
document.write("These doors are open: " + open.join(', '));
outputs
these doors are open: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100
[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] 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.
- 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.
[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] Logo
to doors
;Problem 100 Doors
;FMSLogo
;lrcvs 2010
make "door (vector 100 1)
for [p 1 100][setitem :p :door 0]
for [a 1 100 1][for [b :a 100 :a][make "x item :b :door
ifelse :x = 0 [setitem :b :door 1][setitem :b :door 0] ] ]
for [c 1 100][make "y item :c :door
ifelse :y = 0 [pr (list :c "Close)] [pr (list :c "Open)] ]
end
[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] 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
[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] 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] 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] 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)
/* 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)
/* 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] 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
[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] 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,10,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
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
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] Perl 6
unoptimizedmy @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] PHP
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
[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] 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 pstackShows: [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] 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] 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
unoptimized
close = 0
open = 1
doors = [close] * 100
for i in range(100):
for j in range(i, 100, i+1):
doors[j] = open if doors[j] is close else close
print "Door %d:" % (i+1), 'open' if doors[i] else 'close'
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))
for i in list(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
unoptimized
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
## optimized version... we only have to to up to the square root of 100
seq(1,sqrt(100))**2
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)
[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)
End If
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
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
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
end
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
say
Output:
After 100 passes, the following doors are open:
1
4
9
16
25
36
49
64
81
100
Here is another version, solving it the easy way (version 1).
/*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*j /*square the door number. */
/*An alternative: P=J**2 */
if p>doors then leave /*if too large, we're done. */
say right(p,20)
end
say
Output:
For the 100 doors problem, the following doors are open:
1
4
9
16
25
36
49
64
81
100
Here is 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=100 /*not specified? Then assume 100 doors*/
doors=1000
/* 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*j<=doors /*limit the pass-throughs. */
say right(j**2,20)
end
say
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
(I tried to show as much of Ruby syntax and conventions as possible. Of course, instead of a class you could just use generic true/false, but that's not the point, is it?)
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?
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.f
Closed
end
def Closed.f
Open
end
doors = [Closed] * (n+1)
for mul in 1..n
for x in 1..n
doors[mul*x] = (doors[mul*x] || break).f
end
end
doors.each_with_index {
|b, i|
puts "Door #{i} is #{b}" if i>0
}
optimized
n = 100
(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.inspect
[edit] Run BASIC
dim doors(100)Output:
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
Open doors 1 4 9 16 25 36 49 64 81 100
[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.
"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)(moved from the Racket language entry, may be redundant)
(define (flip-all i)
(cond ((> i (floor (sqrt *max-doors*))) doors)
(else
(vector-set! doors (- (* i i) 1) #t)
(flip-all (+ i 1)))))
(flip-all 1))
(show-doors (optimised-flip-doors (make-vector *max-doors* #f)))
#lang racket
;; Like "map", but the proc must take an index as well as the element.
(define (map-index proc seq)
(for/list ([(elt i) (in-indexed seq)])
(proc elt i)))
;; Applies PROC to every STEPth element of SEQ, leaving the others
;; unchanged.
(define (map-step proc step seq)
(map-index
(lambda (elt i)
((if (zero? (remainder i step) )
proc
values) elt))
seq))
(define (toggle-nth n seq)
(map-step not n seq))
(define (solve seq)
(for/fold ([result seq])
([(_ pass) (in-indexed seq)])
(toggle-nth (add1 pass) result)))
(for ([(door index) (in-indexed (solve (make-vector 100 #f)))])
(when door
(printf "~a is open~%" index)))
optimized:
#lang racket
(for-each (lambda (x) (printf "~a is open\n" x))
(filter (lambda (x)
(exact-integer? (sqrt x)))
(sequence->list (in-range 1 101))))
[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] 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
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
]
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] 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
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] 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 100-doors ()
(let ((doors (vector 100)))
(each ((i (range 0 99)))
(for ((j i)) ((< j 100)) ((inc j (+ i 1)))
(flip [doors j])))
doors))
(each ((counter (range 1))
(door (list-vector (100-doors))))
(format t "door ~a is ~a\n" counter (if door "open" "closed"))))
[edit] UNIX 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] VBScript
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;
[edit] Visual Basic .NET
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] 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
See: 100 doors/XSLT
[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]
- Programming Tasks
- Solutions by Programming Task
- 4DOS Batch
- 6502 Assembly
- 8086 Assembly
- ABAP
- ACL2
- ActionScript
- Ada
- Aikido
- ALGOL 68
- AmigaE
- APL
- AppleScript
- Arbre
- Argile
- AutoHotkey
- Axiom
- AWK
- BASIC
- Batch File
- BBC BASIC
- Befunge
- BlitzMax
- Bracmat
- C
- C Runtime
- C++
- C sharp
- C1R
- CLIPS
- Clojure
- COBOL
- CoffeeScript
- ColdFusion
- Common Lisp
- D
- Dart
- Delphi
- DWScript
- Dylan
- E
- Eiffel
- Ela
- Emacs Lisp
- Erlang
- Euler Math Toolbox
- Euphoria
- F Sharp
- Factor
- Falcon
- Fantom
- Forth
- Fortran
- GAP
- GML
- Go
- Golfscript
- Groovy
- Haskell
- HaXe
- HicEst
- Icon
- Unicon
- Inform 7
- Informix 4GL
- Io
- Ioke
- J
- Java
- JavaScript
- K
- LabVIEW
- Lhogho
- Liberty BASIC
- Logo
- Lua
- M4
- Mathematica
- MATLAB
- MAXScript
- Mercury
- Metafont
- MIPS Assembly
- Mirah
- ML/I
- MMIX
- Modula-2
- Modula-3
- MOO
- MUMPS
- NetRexx
- Objeck
- OCaml
- Octave
- OpenEdge/Progress
- Oz
- PARI/GP
- Pascal
- Perl
- Perl 6
- PHP
- PicoLisp
- Piet
- Pike
- PL/I
- Pop11
- PostScript
- PowerShell
- ProDOS
- Prolog
- PureBasic
- Python
- Q
- R
- REALbasic
- REBOL
- Retro
- REXX
- Ruby
- Run BASIC
- S-lang
- Salmon
- SAS
- Scala
- Sather
- Scheme
- Seed7
- SETL
- Slate
- Smalltalk
- SNOBOL4
- Tcl
- Tk
- TI-83 BASIC
- TI-89 BASIC
- TUSCRIPT
- TXR
- UNIX Shell
- Ursala
- Vala
- VBScript
- Vedit macro language
- VHDL
- Visual Basic .NET
- Wrapl
- XPL0
- XSLT
- Yorick
- GUISS/Omit