• Jonas (unregistered)

## Probably found before me, but here is my solution with recursion in python.

def f(n): if n == 1: return [1] elif n == 4: return [1, 4]

``````tmp = f(n-1)
if n == (tmp[-1] - tmp[-2]) + res[-1] + 2:
tmp.append(n)

return tmp
``````
• port (unregistered) in reply to KukkerMan

This looks good but I can't get it to work in npiet. From the trace it seems to loop round, but it just outputs commas and never stops. The vertical light blue right of centre seems to be an OutC command. Which piet interpreter did you use?

• Alex (unregistered) in reply to Welbog
Welbog:
The open lockers are perfect squares.

The reasoning is simple: non-perfect squares have an even number of factors. The jocks toggle a number for every factor it has. Therefore every door should be toggled an even number of times and should therefore end closed (the starting state).

However, perfect squares have an odd number of unique factors, because one of the factors is repeated. Because of this, perfect squares are toggled for their square root which has no pair to reverse the toggle, so the door ends up open (the opposite state it started in).

Make sense?

Good thinking :)

• Stephan (unregistered)
```function locker(\$amount) {
\$result = array();
\$resultString = '';
for (\$index = 1; \$index <= \$amount; \$index++) {
\$root = sqrt(\$index);
\$result[\$index] = floor(\$root) == \$root;
\$resultString .= ';' . (\$result[\$index] ? '1' : '0');
}
echo substr(\$resultString, 1);
return \$result;
}
```
• troll (unregistered)

Has anyone figured out if there's some sort of pattern to the open doors?

• Emanuele Sabellico (unregistered)

In python:

import math def getOpenLockers(n): return [(x+1)**2 for x in range(0, math.floor(math.sqrt(n)))]

• Daniel (unregistered) in reply to Wongo
If I remember correctly, you could refactor lines 40 and 80 into "IF I>N THEN STOP"
Well, why program in BASIC if you cannot abbuse GOTOs?

The truth is I as having a hard time in typing this program as the emulator follows the ZX81 keyboard layout. I was also too lazy to write it down on paper before entering or to find an image of the Z81 keyboard.

Btw, I bought the 16K expansion from the start, so I could waste a few bytes...

• Josh (unregistered) in reply to Alex Papadimoulis

This is what the function looks like when you just simulate what the jocks are doing in c++ (and you, like myself, are at best a novice programmer). This includes counting the number of times the lockers are flipped and a simple output of the results:

int x, y, locker [100] = {0}, count [100] = {0};

``````for (x=1; x<=100; x++){
for (y=x-1; y<100; y=y+x){
count[y]++;
if (locker[y] == 0)
locker[y] = 1;
else locker[y] = 0;
}
}
cout<<"Current state: \n 0 = closed and 1 = open\n\n";
for (x=0; x<100; x++){
cout<<"Locker "<<setw(3)<<right<<(x+1)<<" :  "<<locker[x]<<" | flipped "<<count[x]<<" times\n";
}
``````
• N Muntz (unregistered) in reply to Maurits
Maurits:
Follow-up question: which lockers are toggled the LEAST?

That's like asking the square root of a million. No one will ever know.

HA-ha.

• Zach Bora (unregistered) in reply to Gabriel
Gabriel:
Pretty simple :) after you watch the simulation... getOpenLockers(n){open = 1;count = 3; while(open<=n) { print open; open += count;count += 2;} } I'll leave the mathematical solution for somebody else.

Umm, the goal is to finish before the jockers!

• Gandalf (unregistered)

There is no need to write code for this. For number, just think about by how many other numbers you can divide it. Note that the locker is opened/closed once for each of those. Obviously, it is important whether the locker number has an odd or an even number of such factors. Now, what numbers do have an odd number of factors? Hint: That depends on the prime factorization.

For each prime factor, take its exponent and add one. Then multiply the results. For example, 12 has 3 * 2 factors because 12 = 2^2 * 3^1. To get an odd result, each prime factor has to appear even times. That means, the locker number has to be a square number. Exactly then the locker will be open in the end.

CAPTCHA: genitus because Gandalf is a genius... with a large genital.

• stangm (unregistered) in reply to Maurits

which lockers are toggled the LEAST? Locker 1, it is only toggled once, every other locker is toggled at least twice.

• Vic Tim (unregistered)

The 60th locker gets toggled the most

that's all I know.

• greg (unregistered) in reply to jocks

sorry, that's brute force. Try again. (hint, no loops allowed)

• Beska (unregistered)

The simple solution is floor(sqrt(n)) where n is the number of lockers (100 in this case.)

That's the easy way to determine how many perfect squares are between 1 and n (without looping).

• brigmar (unregistered) in reply to Mike
Mike:
Now, "In 3009, King Warren of Australia suspects the Earls of Akaron, Bairnsdale, Clearemont, Darlinghurst, Erina and Frankston are plotting a conspiracy against him. He questions each in private and they tell him: Akaroa: Frankston is loyal but Erina is a traitor Bairnsdale: Akaroa is loyal. Claremont: Frankston is loyal buy Bairnsdale is a traitor. Darlinghurst: Claremont is loyal but Bairnsdale is a traitor. Erina: Darlinghurst is a traitor. Frankston: Akaroa is loyal. Each traitor knows who the other traitors are, but will always give false information, accusing loyalists of being traitors and vice versa. Each loyalist tells the truth as he knows it, so his information on traitors can be trusted, but he may be wrong about those he claims to be loyal. How many traitors are there?"

Logic says that :

1: If somebody says somebody else is a Traitor, then they're in the other camp.

2: If two people call each other Loyalists, then they must be in the same camp (a Loyalist couldn't mistakenly identify a Traitor as Loyalist in this case, as the Traitor would identify the Loyalist as a Traitor).

3: If person1 from campX calls person2 from campY a Loyalist, person1 must be a mistaken Loyalist, campX must be Loyalist, and campY must be Traitors, as a traitor would identify a Loyalist as a Traitor.

From 1, it can be deduced that A,D,C fall into 1 group, and E,B fall into the other. A infers E infers D infers B. C infers B.

From 2, F falls into the same camp as A, giving A,D,C,F and E,B as the two groups.

From 3, B is a loyalist, and A is a traitor.

Therefore there are 2 loyalists (B,E) and 4 traitors (A,C,D,F)

• Henkie (unregistered) in reply to Maurits

Most opend and closed is Locker#60 (12 times) least opend and closed is Locker#1 (1 times)

• Grummel (unregistered) in reply to Maurits
Maurits:
Follow-up question: which lockers are toggled the LEAST?
You are not thinking of prime numbers, aren't you?

The first is only toggled once, this seems pretty obvious.

• Henkie (unregistered)

10000 times takes some time to calculate :)

"Most opend and closed is 64 times [lockers 7560, 9240]" "Least openend and closed is 1 time [locker 1]"

100000 times some more :)

And 1 million times takes a whole lot longer :D

• Mike (unregistered)

All prime numbers but 1 (one is a prime number right? lol)...

• Abatcher (unregistered) in reply to Maurits

Locker 1 duh :D

• Joey (unregistered)

Powershell

# getOpenLocker 100

function getOpenLockers(\$n){(1..\$n|%{\$*\$})-le\$n}

# 100 | getOpenLockers

filter getOpenLockers{(1..\$|%{\$*\$})-le\$}

# 100 | % \$getOpenLockers

\$getOpenLockers={(1..\$|%{\$*\$})-le\$}

• Babu (unregistered) in reply to Maurits

The primes

• Fregas (unregistered) in reply to Alex Papadimoulis

the real wtf is that this is on the dailywtf.

how the mighty have fallen. I miss the old days.

• (cs) in reply to greg
greg:
sorry, that's brute force. Try again. (hint, no loops allowed)
"Not brute force" doesn't mean "no loops allowed". The number of elements in the desired output is a monotonic increasing function of the size of the input, so it's impossible to give a correct solution without some form of loop.
• Kevin Kofler (unregistered)

Lemma 1: Let the lockers be numbered starting from 1. Every locker is toggled as often as its number n's number of divisors.

Proof: Consider step k: it toggles lockers k, 2k etc., i.e. all the lockers m such that k divides m. So every k which toggles locker n is a divisor of n. Conversely, every divisor of n will toggle locker n, as all divisors of n are <= n and we run as many steps as there are lockers in total, and thus >= n steps.

Remark: This also answers the bonus questions: The more divisors a number n has, the more often the locker n will get toggled. The numbers which get toggled the least are, after 1 (1 divisor), the prime numbers (2 divisors).

Lemma 2: The locker remains closed if it is toggled an even number of times, it ends up opened if it is toggled an odd number of times.

Proof: By induction. If the locker is toggled 0 times, it remains closed. Let lemma 2 be true for k>0. If k is even, the locker is closed after the kth toggle, k+1 is odd and the locker will be open after the k+1st toggle. If k is odd, the locker is open after the kth toggle, k+1 is even and the locker will be closed after the k+1st toggle.

Lemma 3: The nth locker remains closed if n has an even number of divisors, it ends up opened if n has an odd number of divisors.

Proof: Follows from lemmas 1 and 2.

Theorem: Locker n will end up opened if and only if n is a perfect square.

Proof: Let k be a divisor of n such that kk!=n. Then n/k!=k and n/k is also a divisor of n. It follows that any n which is not a perfect square has an even number of divisors, because kk cannot equal n for a non-square and because n/(n/k)=k and thus (k,n/k) form pairs. By lemma 3, the locker will stay closed. Now let n be a perfect square and m be the square root of n. The number of divisors != m is even by the same reasoning as for non-square n. Thus, counting m too, the number of divisors is odd. By lemma 3, the locker will be open.

Lemma 4 (used in the implementation): (i+1)(i+1)=ii+2i+1=ii+i+(i+1)

Proof: Basic algebra.

Thus the function:

```unsigned *getOpenLockers(unsigned n)
{
unsigned i, i2, *b=calloc(n, sizeof(unsigned)), *p=b;
for (i=1, i2=1; i2<=n; i2+=i, i++, i2+=i) {
*(p++) = i2;
}
return b;
}```

Test code:

```unsigned n=100;
unsigned *p=getOpenLockers(n);
unsigned i;
for (i=0; i<n; i++) {
if (!*p) break;
printf("%u ", *(p++));
}
printf("\n");</pre>
```
• Kevin Kofler (unregistered) in reply to pjt33
pjt33:
greg:
sorry, that's brute force. Try again. (hint, no loops allowed)
"Not brute force" doesn't mean "no loops allowed". The number of elements in the desired output is a monotonic increasing function of the size of the input, so it's impossible to give a correct solution without some form of loop.
Any loop which loops over all lockers is brute force. Look at my solution (maybe given by others first, I haven't read through all the comments), it only takes 1 loop iteration per open locker. (And no, you can't get the complexity down further as you need to produce the output, so you need at least 1 write per open locker.) I shall also remark that my solution requires no multiplication and definitely no square root.
• Kevin Kofler (unregistered)

PS: The bottleneck in my C implementation is the calloc for the buffer. An elegant optimal solution would be using coroutines rather than a buffer. A less elegant way to do away with the buffer is to use an iterator-style API, which can easily be implemented in C:

```static unsigned n, i, i2;

unsigned firstOpenLocker(unsigned N)
{
n = N;
i = i2 = 1;
return 1;
}

unsigned nextOpenLocker(void)
{
i2 += i;
i++;
i2 += i;
return (i2 > n) ? 0 : i2;
}```

Test code:

```unsigned n=100;
unsigned k=firstOpenLocker(n);
do {
printf("%u ", k);
k = nextOpenLocker();
} while (k);
printf("\n");```
• RMB (unregistered)

import Array (assocs, accumArray) main :: IO () main = let n = 100 in print (map fst (filter snd (assocs (accumArray (\x () -> not x) False (1,n) [(k,())| m<-[1..n], k<-[m,2*m .. n]]) )))

• Papa Troll (unregistered) in reply to troll
troll:
Has anyone figured out if there's some sort of pattern to the open doors?
Not yet. Keep reading.
• Tom (unregistered) in reply to Maurits

Duh... the first one!

Some things I've noticed:

• on the i-th iteration, the i-th locker is in its final state

• each locker is toggled a number of times equal to the number of its factors, e.g.: every locker number has 1 as a factor hence they all get toggled at least once. Another e.g.: locker # 4 has 4,2,1 as factors (or divisors, or whatever you want to call them) so it's toggled thrice (yep, I said thrice)

• finally, (a bit obvious) lockers toggled odd number of times finish in the opposite state to which they started; even number of times: same as they started

• (cs) in reply to Daniel

There is bug somewhere. E.g. try input 16: the last one should be open but it's shown closed.

Addendum (2009-08-09 15:16): BTW I've put index online. Available from here.

• Graysen (unregistered)

I'm VERY new to any programming (about 2 months), this is what I came up with in C++. If anyone has a suggestion to make the code better I would really appreciate it. This is based on open = True and closed = false. The correct lockers are open but I'm not sure of how to get rid of 0.

```#include <iostream>

using namespace std;

void swap (int *p1);
int lockers[101];
int i, s;

int main()
{
for (s = 1; s < 101; s++){
for (i = s; i < 101; i = i + s){
swap (&lockers[i]);
cout << i << " - " << lockers[i] << " // ";
}
cout << "\n";
cout << "\n";
}

for (i = 0; i < 101; i++)
cout << i << " - " << lockers[i] << " // ";

return 0;
}

void swap (int *p1){
if (*p1 == false)
*p1 = true;

else
*p1 = false;
}
```
• (cs)

Requirements Counter-Strike:Source Eventscripts 1.5 installed on server

Installation place script in the file

`\cstrike\addons\eventscripts\wtf_lockers\es_wtf_lockers.txt`

Usage Create local Counter-Strike:Source server Type the following in console:

```es_load wtf_lockers
lockers 100
nerds
```

The results will be the following:

```Nerds, Jocks, and Lockers loaded
Number of Lockers = 100
Toggling Lockers...
1
4
9
16
25
36
49
64
81
100
Toggled Lockers!
Nerds, Jocks, and Lockers unloaded
```

Script

es_wtf_lockers.txt:
```// Programming Praxis: Nerds, Jocks, and Lockers
{
es_xsetinfo num_lockers 0
es_xsetinfo count 1
es_xsetinfo square 0
es_xsetinfo done 0
```es_regclientcmd lockers wtf_lockers/set_lockers
es_regclientcmd nerds wtf_lockers/start

es_xmsg #multi #greenNerds, Jocks, and Lockers loaded
```
}
{
es_xmsg #multi #greenNerds, Jocks, and Lockers unloaded
}
block set_lockers
{
es_getargv num_lockers 1
es_msg Number of Lockers = server_var(num_lockers)
}
block start
{
es_xmsg #multi #greenToggling Lockers...
es_doblock wtf_lockers/lockers
}
block lockers
{
es_setinfo square server_var(count)
es_math square power 2
if (server_var(square) greaterthan server_var(num_lockers)) do
{
es_xsetinfo done 1
}
```if(server_var(done) equalto 0) do
{
es_msg server_var(square)
es_math count add 1
es_doblock wtf_lockers/lockers
}
else do
{
es_xmsg #multi #greenToggled Lockers!
}
```
}
```
• onnie (unregistered) in reply to Maurits

This will probably segfault... but

/* it is the sqrt of the MAX_LOCKERS +1 #define DEF_MAX_LOCKERS 65 /* up to 4096 doors */ typedef struct lockers_s { uint32_t OpenLocks[DEF_MAX_LOCKERS]; uint32_t numOpenLocks; } lockers_t;

lockers_t getOpenLockers(uint32_t lockerCount) { lockers_t lockers; uint32_t tmp; uint32_t count; lockers.numOpenLocks = (uint32_t) sqrt(lockerCount); if (lockers.numOpenLocks == 0) return lockers;
/* only pure squares are left open / for (count = 1; count <= lockers.numOpenLocks; count++) { lockers.OpenLocks[count-1] = countcount; } /* and the last one if not already in the list / if (countcount != lockerCount) { lockers.OpenLocks[count] = lockerCount; lockers.numOpenLocks++; } return lockers; }

• (cs)

I submit that while Mr. Zargas may have been "zany" he wasn't as whacked as his distant cousin Mr. Zargus whom it seems should have been the one to take it a step further, though it was actually "Mr. Zargas' locker challenge".

• W. Craig Trader (unregistered)

```def getOpenLockers( n ):
i = 1
while ( i*i <= n ):
answer += [ i*i ]

```
• neried7 (unregistered)

#!/usr/bin/perl

use warnings; use strict;

sub lockers {

``````print "Enter a number of lockers: ";
chomp(my \$n = <STDIN>);
my @lockers; #0 index will be ignored. So will 1 because those are all open to start.
if (\$n == 1) {
@lockers = (1);
print @lockers;
return @lockers;
}

# 1 means open, 0 means closed. For \$n > 1, the first round opens all lockers.

my (\$i, \$j);
for (\$i=1; \$i<=\$n; \$i++) {
for (\$j=1; \$j<=\$n; \$j++) {
if (\$j % \$i == 0) { # if the divisor i is a factor of j, there will be no remainder, and we toggle the locker.
if (\$lockers[\$j] == 1) {
\$lockers[\$j] = 0;
} else {
\$lockers[\$j] = 1
}
}
}
}

print "Final lockers: \n";
for (\$i=1; \$i<=\$n; \$i++) {
print "Locker \$i: \$lockers[\$i] \n";
}
return @lockers;
``````

}

&lockers;

• TopicSlayer (unregistered) in reply to Mike
Mike:
Now, "In 3009, King Warren of Australia suspects the Earls of Akaron, Bairnsdale, Clearemont, Darlinghurst, Erina and Frankston are plotting a conspiracy against him. He questions each in private and they tell him: Akaroa: Frankston is loyal but Erina is a traitor Bairnsdale: Akaroa is loyal. Claremont: Frankston is loyal buy Bairnsdale is a traitor. Darlinghurst: Claremont is loyal but Bairnsdale is a traitor. Erina: Darlinghurst is a traitor. Frankston: Akaroa is loyal. Each traitor knows who the other traitors are, but will always give false information, accusing loyalists of being traitors and vice versa. Each loyalist tells the truth as he knows it, so his information on traitors can be trusted, but he may be wrong about those he claims to be loyal. How many traitors are there?"
The easiest starting place is E, because he only names a single traitor.

E is either loyal or a traitor; let's assume he is a traitor.

If E is a traitor then he is lying about D being a traitor, in which case D must be loyal. Therefore, D's information about all traitors must be true (while his knowledge of loyalists may be wrong). If that is the case, then D must be correct about B being a traitor. If B was a traitor, then he is lying about A being loyal. Therefore A must be a traitor. If A were a traitor then he must be lying about E being a traitor, and therefore E must be loyal. However, this contradicts E being a traitor, and therefore E must be loyal. We have proven E must be a loyal by contradiction.

If E is loyal (and he must be) then D must be a traitor. If D is a traitor then he's lying about both B and C. Therefore, B must be loyal and C must be a traitor. If C is a traitor then he is lying about B and F. Therefore, B is loyal (we knew already) and F is a traitor. If F is a traitor then A is a traitor. If A is a traitor then E is loyal (we knew this) and F is a traitor (also known.).

So, in the order we figured it out:

Loyal: E, B Traitors: D, C, F, A

• neried7 (unregistered)

First was the brute version, here's the 'formulaic' version:

use warnings; use strict;

sub lockers {

``````print "Enter a number of lockers: ";
chomp(my \$n = <STDIN>);
my @lockers; #0 index will be ignored.

if (\$n == 1) {
@lockers = (1);
print @lockers;
return @lockers;
}

# 1 means open, 0 means closed. For \$n > 1, the first round opens all lockers.
my (\$i, \$j);

#the ones that stay open are the perfect squares, because they end up with
#an odd number of toggles, and thus end up open (opposite of the starting state)

for (\$j=1; \$j<=\$n; \$j++) {

@lockers[\$j] = 0;
}

my \$root_n = sqrt \$n;
print "Square root: \$root_n";

for (\$i=1; \$i<=\$root_n; \$i++) {
\$lockers[\$i**2] = 1;
}

print "Final lockers: \n";
for (\$j=1; \$j<=\$n; \$j++) {
print "Locker \$j : \$lockers[\$j] \n";
}
return @lockers;
``````

}

&lockers;

• (cs)

In the simulation every opened locker adheres to the rule 2^n, except for #9.

I suspect there is a flaw in the simulation.

• (cs) in reply to fuffuf
fuffuf:
In the simulation every opened locker adheres to the rule 2^n, except for #9.

I suspect there is a flaw in the simulation.

Oh, really? What about 25, 36, 49, 81, 100 ?

• Gandalf (unregistered)

As I said before, exactly the lockers with a square number (i.e. n^2) get an odd number of toggles. That is because they have an odd number of divisors.

Obviously, locker 1 is toggled only once because 1 has only one divisor, itself.

To see which locker is toggled most times, consider which number has the highest number of divisors. For this, we only need to consider the prime factors 2, 3, and 5. (Otherwise, the number gets too large.)

So, the only real candidates are 64, 96, and 60. (If you don't understand this, go to a silent place and meditate about prime factors for some time.)

64 = 2^6 has 7 divisors 96 = 2^5 * 3^1 has 62 = 12 divisors 60 = 2^3 * 3 * 5 has 42*2 = 16 divisors

So 60 is toggled most often. 16 times.

• Moomoo (unregistered) in reply to Maurits

locker number 1....

• Wintermute (unregistered) in reply to Gandalf
Gandalf:
60 = 2^3 * 3 * 5 has 4*2*2 = 16 divisors

So 60 is toggled most often. 16 times.

I'm not really sure about that. I did not check the math, though (wrong time of day for that). From my point of view the divisors of 60 are 1,2,3,4,5,6,10,12,15,20,30 and 60, which makes 12. Did I miss any? So most toggles have (according to my brute-force approach) 60,72,84,90 and 96 -> 12 toggles.

For 1.000.000 it's... 720.720 and four more (240 toggles).

• (cs) in reply to mol1111
mol1111:
fuffuf:
In the simulation every opened locker adheres to the rule 2^n, except for #9.

I suspect there is a flaw in the simulation.

Oh, really? What about 25, 36, 49, 81, 100 ?

There are two perfectly good explanations for those, depending on what you think "^" does.

Explanation 1:

25 = 2^27 36 = 2^38 49 = 2^51 81 = 2^83

Explanation 2: 25 = 2^4.64 36 = 2^5.17 49 = 2^5.615 81 = 2^6.34

Clear as mud.

• Gandalf (unregistered) in reply to Wintermute

Uh, yeah, you are absolutely right, Wintermute. I accidentally counted the divisors of 120.

60 = 2^2 * 3 * 5 has 322 = 12 divisors

• (cs) in reply to Maurits
Maurits:
mol1111:
fuffuf:
In the simulation every opened locker adheres to the rule 2^n, except for #9.

I suspect there is a flaw in the simulation.

Oh, really? What about 25, 36, 49, 81, 100 ?

There are two perfectly good explanations for those, depending on what you think "^" does.

Explanation 1:

25 = 2^27 36 = 2^38 49 = 2^51 81 = 2^83

But if you mean XOR, than you can do: 9 = 2^11

In fact, for any x you can find y such as x=2 xor y, so it would not be any rule anyway.

Clear as mud.

I would say so.

• (cs)
```public static List<bool> BeatTheJocks(int numberOfLockers)
{
List<bool> lockers = new List<bool>();
for (int i = 0; i < numberOfLockers; i++)
for (int i = 2; i <= numberOfLockers; i++)
for (int j = i; j <= numberOfLockers; j = j+i)
lockers[j-1] = !lockers[j-1];
return lockers;
}```
• (cs) in reply to mol1111
mol1111:
In fact, for any x you can find y such as x=2 xor y, so it would not be any rule anyway.

y = x xor 2, in fact.

In fact, for any x and y you can find z such that x = y xor z (specifically, z = x xor y)

For my next trick, I will crack ROT13...