- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Delphi
Admin
It looks like this works:
n = number of soldiers k = skip ahead interval (3 in this example) i = "safe spot" index (1-based)
Admin
Of course that is Excel + VBA, not pure VBA.
VBA's bad reputation drives me nuts...it's a good language for what it's intended uses are...so I can't help but be the ass who points out:
1)There's no need to manipulate values on a worksheet, you can use variables and it will run much faster. Each time code touches a worksheet object you pay a large price in speed. Better to do everything in memory and only kick the final result. You can also use Debug.Print to write to the immediate window. Do While Range(checker).Value > 1 will perform much better if replaced by a check against an internal variable, particularly for large loops.
You should use Columns("A:D").ClearContents instead of four separate calls; faster to both write and run. No need to clear columns if you keep data in memory. (arrays?)
It's a bad habbit to use code like: Range(somthing).Method, doing this will break if you accidentally activate a different worksheet while the code is running. When you reference "Range", you are implictly saying Application.ActiveWorksheet.Range, which users can break easily. It's much better to explictly declare which worksheet you want to operate on, using something like sheet1.Range(something) or Worksheets("ExternalSheetName").Range(something) (and bonus points if you use with blocks to reduce the number references to higher level objects)
No need to type cast strings when using & for string concatination. strMyString = "Some Text " & i runs faster than strMyString ="Some text" & Cstr(i)
using code to write worksheet functions is a bit much, there are times where that is useful, but you have the values in code so why not just add them in code too?
Dim cur As String: cur = "C" & CStr(j), not sure if this is considered bad form or not, but I'd wager dimming a var inside a loop slows things significantly. You're replacing the value of this variable each time, no need to redim it.
Admin
No no, he's right, you don't start over after each round, it's round robin! The last spot is 5!
In any case, if there are n soldiers and you kill every kth, there one position where you should never ever stand: kth.
Admin
Quote fail...that was in reference to the vba post on page 1...
Admin
for 1 + (n-1)k mod n: 1 + (17-1)2 mod 17 = 1 + 32 mod 17 = 16, which is incorrect. for 1 + (n-1)(k-1) mod n: 1 + (17-1)(2-1) mod 17 = 1 + 16 mod 17 = 17, which is also incorrect.
I assumed you mean % as taking precedence over addition, in C fashion. However, even if you actually meant (1 + (n-1)k) mod n or (1 + (n-1)(k-1)) mod n for 17,2 the results are 16 and 0, respectively. Also incorrect.
Admin
{1,2,3,4,5} => {1,3,4,5} => {1,3,5}. We begin counting now at 5, which is skipped, so remove 1: {3,5}. We begin count now at 3, which is skipped, so remove 5: {3}
Admin
By looking at that sequence I was able to come up with the following javascript solution:
function josephus3(count, seed) { var index = seed % 2 == 0 ? 1 : 2;
}
First we determine the starting index based on whether the seed is even or odd.
Next we follow the pattern of the solution above, which is, every time you go up from two you add the seed to the index and if the new index is greater than i (the number of men) you subtract i.
I expected this to work with a seed of 3, but I was surprised when I found out it works with any seed. It was easy for me to write an algorithm to represent the pattern, whereas I don't think I could figure out the other more elegant approaches.
Admin
How's about a T-SQL function? I could probably tighten this up considerably but it works.
Admin
Brilliant! It works perfectly! Congrats, db2, you made my day!
Now, if we could just remove the loop and turn it into a formula, we might find out how Josephus did it "very quickly"...
Admin
Clojure!
Most of this function is just the definition for the ax() function.
Admin
JavaScript 1.8:
Non-recursive form:
As mentioned at Wikipedia, a closed form exists for k = 2: j(n, 2) = 2 * (n - 2 ^ log2(n)) There is no closed form for k = 3; a good place to start is OEIS A054995.
Admin
Woops, that should be unset($roulette[$arrayIndex]); not unset($roulette[$value]);
Why must comments keep erroring out?
Admin
You're right, I misunderstood the original reasoning from halber_mensch (and yours too). The last spot is indeed 3.
Admin
Other than that, all these solutions appear to assume a boolean state for each soldier of dead/alive. Whatever happened to death_not_found?
Admin
My formula is wrong, because I forgot about the modulus :) It changes when you reduce the problem in size... mod n, mod n-1 etc. Sorry for wasting yout time :)
Admin
Naive, very much to the letter solution in Scheme:
And a test session:
Admin
Edit: Use one-based index
Addendum (2009-07-29 14:13): (q is "number to skip", so kill every q+1 th) -- I originally had it the other way but then edited it.
Admin
The solution is:
"Hey everyone, I'll watch the door while you guys sort this out."
Admin
Nah, I knew you were on to something... Couldn't have found it myself anyway (or maybe with lots more time).
Admin
Granted, I haven't tested it for other values of k, or for weird edge cases, but I was able to precisely reproduce your list of safe spots by putting a Console.WriteLine() at the bottom of the loop body.
Admin
Sure, all these new language codes are pretty good, but I'd really like to see somebody come up with a Turing Machine solution.
Admin
My perl approach:
78 chars :-)
Admin
No, you were right the first time. 5 is the last man standing because you eliminate the person on the kth count, which in this case is 1, so you just kill everybody from the start of the list. You don't skip 1. Look at the animated GIF in the article to confirm this. It counts to three and kills the guy on 3, not the guy after 3.
Admin
I'd like to see somebody come up with a solution that works on 1st century A.D. technology.
Admin
Iterative and runs in logarithmic time
Addendum (2009-07-29 14:08): NOTE: m is number to skip as listed in article -- so every m+1 is killed.
Admin
Why Prolog gets no love... K is step size, I is 0 based index, N is number of unluckies.
Cut is not absolutely necessary.
Admin
Admin
Here's another javascript version
Admin
Good old C. Still no 860 iterations. First method 398 steps; recursive method does n-1 recursions; iterative solution loops n-1 times.
Admin
Here's another Python version that replaces the recursion with a for loop. Same basic solution, but without the potential memory issue.
Admin
this should be fitting for the daily wtf
struct position{ int id; position * nextGuy; position * lastGuy; };
int safe(int people, int count){ position * circle = new position; position * head = circle;
circle->id = 1; for ( int c = 2; c < people+1; c++){ position * temp = new position; temp->id = c; temp->lastGuy = head; head->nextGuy = temp; head = temp; } circle->lastGuy = head; head->nextGuy = circle;
while( circle->lastGuy != circle->nextGuy ){ for(int c = 0;c < count; c++ ){ circle = circle->nextGuy; } head=circle; circle=circle->nextGuy;
}
int result = circle->id; delete circle; return result; }
Admin
Give me n soldiers and an axe.
Admin
Perl Golf. 83 characters including perl -e and the two given arguments 40 and 3. 69 characters between the quotes.
perl -e"@=(1..$ARGV[0]);++$c%$ARGV[1]?$i++:splice@,$i%=@,1while$#;print@_" 40 3
Addendum (2009-07-29 13:24): Shaved off three characters by using "shift" instead of $ARGV[0].
80 characters for the whole thing; 66 between the quotes.
http://blogs.msdn.com/matthew_van_eerde/archive/2009/07/29/bad-perl-josephus-problem.aspx
Addendum (2009-07-29 14:00): 78/64 dropping the parentheses.
Addendum (2009-07-29 14:09): Actually dropping the parentheses.
Admin
Ops!
In LoopSurvay, please change
pos = (pos + k) % n;
to
pos = (pos + k) % (i+1);
Admin
public string DoJosephus(int soldiersCount, int soldiersToSkip) { List<string> soldiers = new List<string>(soldiersCount); for (int j = 0; j < soldiersCount; j++) soldiers.Add((j+1).ToString()); int i = soldiersToSkip - 1; do { i = GetStep(i, soldiers.Count); soldiers.RemoveAt(i); if (i + soldiersToSkip > soldiers.Count) i = i - soldiers.Count; i = i + soldiersToSkip - 1;
Admin
A batch file solution:
@echo off rem - argument 1 is number of soldiers, argument 2 is the number to count to each time
call :josephus %1 %2
echo the survivor is at index %survivor% exit /b
:josephus set soldiers=%1 set /a soldiersnext="soldiers-1" set count=%2 if %soldiers% neq 1 call :josephus %soldiersnext% %count% set soldiers=%1 set /a survivor="(count+survivor)%%soldiers" exit /b
Admin
In response to Wongo:
There's a formula in the Online Encyclopaedia of Integer Sequences: http://www.research.att.com/~njas/sequences/A054995
Not the simplest looking thing, but still not bad (compared to what I usually have to look at).
Admin
I thought there needed to be three pointers to the same object.
Admin
Wrote this during my lunch break. Compiles in Turbo Pascal 5.0, uses pointers...
Admin
Thank you, CLR.
Admin
What have I learned today?
If I'm going to have a Judeo circle of mass [suicide|assisted suicide], be the one who announces the skip number AFTER the circle is formed.
Admin
yes the last
push into an array all the loosers with a for loop that counts 3 and inside the for put an if for checking the actual array if is in the array dont push it and continue checking the array of the standing soldiers
for this u need 2 arrays one for loop and put it into a function and done
my inglish is bad i know
:)
Admin
k is the skip, count is k+1. You count to three and thus skip over two guys. 1 2 3 4 5 6 7 8 9 etc. If your count is one, your k is 0 in which case J(5,0) yields 5. But our count is 2 and the k is 1 to skip every other guy.
Admin
Admin
God, that took me so much longer than it should have - and I'm not even proud of the code :-(
Anyways, here goes my python implementation:
Admin
Just for the fun of it: A Haskell version featuring infinite recursion.
Admin
powershell
Admin
Note: m is the "number to skip" as in the spec, so you kill every m+1 th
Addendum (2009-07-29 17:09): This is intended to model the actual chopping process, not to be efficient.
Admin
Just started learning Haskell so ... but this seems to work
-- josephus try
joHelper xs = if null (drop 2 xs) then drop 1 xs else joHelper ((drop 3 xs) ++ (take 2 xs))
josephus i = head (joHelper [1..i])