Die eingegangenen Lösungen von @Rolf B, @1unitedpower, @Camping_RIDER, @Gunnar Bittersmann und @encoder, empfinde ich zum Teil deutlich eleganter als meine, ich überlasse es ihnen, sie hier zu posten.
Zeigst du uns deine Lösung denn trotzdem?
Ich habe Haskell bemüht:
module Prisoners where
type Index = Int
type Size = Int
type Prisoner = Int
-- n Gefangene haben sich in einem Kreis aufgestellt und wurden beginnend mit
-- 1 durchnummeriert. Angefangen mit dem (i+k)-ten Gefangen wird nun jeder
-- k-te Gefangene zurück in seine Zelle geschickt, bis noch k-1 Gefangene übrig
-- sind, welche dann begnadigt werden.
-- Die Funktion `actOfGrace` liefert die Nummern der k-1 Gefangenen, die
-- entlassen werden.
actOfGrace :: Index -> Index -> Size -> [Prisoner]
actOfGrace k i n = dropKth k (i-1) [1..n]
-- Angefangen mit dem (i+k)-ten Element, entferne jedes k-te Element aus einem
-- Ring bis nur noch k-1 Elemente übrig sind. Die Zählung beginnt mit 0.
dropKth :: Index -> Index -> [a] -> [a]
dropKth k i xs
= if (length xs == k - 1) -- Abbruchbedingung erreicht?
then xs -- Finales Ergebnis
else dropKth k i' xs' -- Entferne ein Element rekursiv
where
out = (i + k - 1) `mod` (length xs) -- zu entferneder Index
xs' = remove out xs -- Ring um ein Element verkürzt
i' = out `mod` (length xs') -- Beginn nächster Zählung
-- Entferne das n-te Element aus einer Liste. Die Zählung beginnt mit 0.
remove :: Index -> [a] -> [a]
remove n xs
= (take n xs) ++ (drop (n+1) xs)
-- Test mit 10 Gefangenen, Zählbeginn bei 1 und jeder 3-te wird zurück auf die
-- Zelle geschickt bis nur noch 2 übrig sind.
test :: Bool
test
= expected == actual
where
expected = [4, 10]
actual = actOfGrace 3 1 10
Aber wenigstens die while-Schleife habe ich auch verwendet
In Haskell gibt es keine while-Schleifen oder irgendwelche Schleifen, da muss man auf Rekursion zurückgreifen. Das schöne an der Aufgabenstellung war, dass der Start-Index frei wählbar war, dadurch ergibt sich fast von alleine eine Tail-Rekrusion, die von Haskell automatisch so optimiert wird, dass der Callstack nicht anwächst.