VB.NET Josephus Problem, blutiger Anfänger

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 51 Antworten in diesem Thema. Der letzte Beitrag () ist von nogood.

    Beim 11-er gehe ich genau so vor wie beim 4-er.

    Habs jetzt oben hingeschrieben. Kann es auch hier nochmals schreiben.

    n = 11, k = 7. Der Index 6 (0-basieren) bekommt die Personenzahl 1, der Index 2 (Position 13 % 11 = 2) bekommt die Personennummer 2 , die nächste Position wäre 21, das ist der Index 10 mit Personennummer 3 etc.

    Position 17 (17 % 11 = Index 6) wird übersprungen, da schon besetzt.
    Gut, ob man jetzt immer dieselbe Liste hernimmt oder 2 (wie ich, siehe Post#37) kann man ja machen wie man will. Kommt eben drauf an, was man für die weitere Handhabung (Berechnung/Auflistung) einfacher findet.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich habe bei meinem Algo den Iter einfach immer weiter zählen lassen. Das macht schlussendlich den Algo zwar ein bisschen langsamer, aber ich finde ist genau so wirksam. Wie die Zahlen schlussendlich daher kommen, habe ich bis jetzt auf keiner Tabelle im Netzt gefunden.

    Ich denke wenn's Schlussendlich mit der Permutation (egal in welcher Reihenfolge) klappt, ist es sicher eine Lösung für das Josephius-Problem.

    Ich habe meine mit der auf Wiki beschriebenen Methode gegeneinander ausgespielt. Der Endwert ist immer identisch.
    Hier doch noch eine Änderung. Beim Konvertieren von C# zu VB hatten sich ein paar Zeilen Eingeschlichen die nicht nötig sind. Oder es geht doch noch kürzer u. einfacher 41 Zeilen übrig:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Module Module1
    2. 'Klasse Person
    3. Public Class Person
    4. Public Property Id As Integer
    5. Public Sub New(nr As Integer)
    6. Id = nr
    7. End Sub
    8. End Class
    9. 'Hauptprogramm
    10. Private NochStehendePersonen As List(Of Person) = New List(Of Person)()
    11. Sub Main()
    12. For i As Integer = 1 To 1000
    13. NochStehendePersonen.Add(New Person(i))
    14. Next
    15. Console.WriteLine("1000 Personen stehen im Kreis jeder siebte setzt sich hin bis nur noch drei stehen:")
    16. Play(NochStehendePersonen)
    17. Console.WriteLine("Es stehen zum Schluss noch Position:")
    18. For Each p As Person In NochStehendePersonen
    19. Console.WriteLine(p.Id)
    20. Next
    21. Console.ReadLine()
    22. End Sub
    23. 'Methode Play
    24. Private CounterStehender As Integer = 0
    25. Private Sub Play(ByVal personen As List(Of Person))
    26. If personen.Count() <= 3 Then
    27. Return
    28. End If
    29. NochStehendePersonen = New List(Of Person)()
    30. For Each p As Person In personen
    31. CounterStehender += 1
    32. If CounterStehender <> 7 Then
    33. NochStehendePersonen.Add(p)
    34. End If
    35. If CounterStehender = 7 Then
    36. CounterStehender = 0
    37. End If
    38. Next
    39. Play(NochStehendePersonen)
    40. End Sub
    41. End Module
    codewars.com Rank: 4 kyu

    nogood schrieb:

    @Benutzername Ich kann mich noch zu gut an die Zeit erinnern. Hier heute mal ein Freilos (vorausgesetzt, dass meine Lösung stimmt)!

    Visual Studio neues Consolen Vb.net App Framework Projekt erstellen und Copy Paste
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Module Module1
    2. '//Bauplan Person mit nur einer Eigenschaft jede Person hat seine "Sitz/Stehplatznummer"
    3. Public Class Person
    4. Public Property Id As Integer
    5. Public Sub New(nr As Integer)
    6. Id = nr
    7. End Sub
    8. End Class
    9. '//^^^Bauplan Person Ende
    10. '//Hauptprogramm
    11. '//Liste mit dem Namen "Personen" die Person-Objekte enthält wird reserviert
    12. '//Konvention ist die Liste im Plural der enthaltenden Ojekte zu benennen
    13. '// Also Personen = Liste of Person
    14. Public Personen As List(Of Person) = New List(Of Person)()
    15. Sub Main()
    16. '//Erzeugung der Liste Personen = (Person(Id=1), Person(Id=2), ... Person(Id=1000))
    17. For i As Integer = 1 To 1000
    18. Personen.Add(New Person(i))
    19. Next
    20. Console.WriteLine("1000 Personen stehen im Kreis jeder siebte setzt sich hin bis nur noch drei stehen:")
    21. '//erster Aufruf von Play mit der Liste der 1000 Personen
    22. Play(Personen)
    23. '//Ergebnis Darstellung in der ehemals 1000 Personen Liste stehen nur noch 3 drin
    24. Console.WriteLine("Es stehen zum Schluss noch Position:")
    25. For Each p As Person In NochStehendePersonen
    26. Console.WriteLine(p.Id)
    27. Next
    28. Console.ReadLine()
    29. End Sub
    30. '//^^^Hauptprogramm Ende
    31. '//Play Methode (o. auch Funktion genannt) die die "echte Arbeit" macht und die Position findet
    32. Private CounterStehender As Integer = 0
    33. Private NochStehendePersonen As List(Of Person) = New List(Of Person)()
    34. Private Sub Play(ByVal personen As List(Of Person))
    35. '//Abbruch Kriterium
    36. If personen.Count() <= 3 Then
    37. '//Übergabe der Liste der Stehenden Personen nach "außerhalt" der Play Methode
    38. '//falls da dann nur 3 drin stehen wird die Play Methode ja abgebrochen
    39. personen = New List(Of Person)()
    40. personen.AddRange(NochStehendePersonen)
    41. Return
    42. End If
    43. '//Neue Liste der jetzt noch stehenden Personen wieder bei null anfangen
    44. NochStehendePersonen = New List(Of Person)()
    45. '//jeder 7 setzt sich hin
    46. For Each p As Person In personen
    47. CounterStehender += 1
    48. If CounterStehender <> 7 Then
    49. NochStehendePersonen.Add(p)
    50. End If
    51. If CounterStehender = 7 Then
    52. CounterStehender = 0
    53. End If
    54. Next
    55. '//Rekursion: die Methode Play wird jetzt mit dieser Liste(PersonenDieNochStehen) neu aufgerufen bis
    56. Play(NochStehendePersonen)
    57. End Sub
    58. '//^^^Play Ende
    59. End Module


    webspace.ship.edu/deensley/mathdl/Joseph.html



    Das ist beeindruckend. Danke auch für die Kommentare dazu.

    Wie ist denn folgender Code zu bewerten? Das ist noch etwas, was ich online gefunden habe und auch ungefähr meinem bisherigen Verständnis entspricht/entsprechen sollte. Quelle des Codes
    Hierbei ist auch wieder das altbekannte Josephus-Problem zu lösen allerdings nicht wie in meiner Aufgabenstellung mit 1000 Personen/jede 7. Person.

    Anhand der bisherigen zwei Seiten Skript über Enumerationen bzw. zwei Seiten über Listen, kann ich den Code leider nicht entziffern. Woher weiß denn das Programm, um wie viele Personen es insgesamt geht bzw. wie groß der Abstand zwischendrin ist?
    Besteht zwischen Zeile 4 und Zeile 17 bzw. 19 ein Zusammenhang? Wieder möglicherweise falsch ausgedrückt sehe ich, dass in Zeile 4 in Sub Josephus drei Variablen (n, k, m) in der Klammer stehen bzw. initialisiert wurden und sich in Zeile 17 bzw 19 ebenfalls 3 Zahlen in der Klammer befinden.

    VB.NET-Quellcode

    1. Module Module1
    2. 'Determines the killing order numbering prisoners 1 to n
    3. Sub Josephus(n As Integer, k As Integer, m As Integer)
    4. Dim p = Enumerable.Range(1, n).ToList()
    5. Dim i = 0 Console.Write("Prisoner killing order:")
    6. While p.Count > 1 i = (i + k - 1) Mod p.Count
    7. Console.Write(" {0}", p(i))
    8. p.RemoveAt(i)
    9. End While
    10. Console.WriteLine()
    11. Console.WriteLine("Survivor: {0}", p(0))
    12. End Sub
    13. Sub Main()
    14. Josephus(5, 2, 1)
    15. Console.WriteLine()
    16. Josephus(41, 3, 1)
    17. End Sub
    18. End Module



    Edit: mittlerweile habe ich durch ausprobieren herausgefunden, dass Zeile 17 bzw. 19 tatsächlich die Anzahl der Personen und den Abstand untereinander angeben. Was die letzte Ziffer soll, oben als m deklariert, habe ich nicht herausgefunden, da mir die Software auch sagt "IDE0060 Remove unused parameter 'm' " in zeile 4

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Benutzername“ ()

    Ich hab das ganze mal als reine Index-Rechnung formuliert:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. ' Werte von WiKi
    4. Dim Anzahl = 41
    5. Dim Modulo = 3
    6. Dim Rest = 2
    7. If True Then
    8. ' Werte vom Forum
    9. Anzahl = 1000
    10. Modulo = 7
    11. Rest = 3
    12. End If
    13. Dim ll = Josephus(Anzahl, Modulo, Rest)
    14. For i = 0 To ll.Count - 1
    15. ListBox1.Items.Add(ll(i))
    16. Next
    17. End Sub
    18. Private Function Josephus(Anzahl As Integer, Modulo As Integer, Rest As Integer) As List(Of Integer)
    19. Dim ll = New List(Of Integer)
    20. ' Aufstellen der Delinquenten
    21. For i = 1 To Anzahl
    22. ll.Add(i)
    23. Next
    24. Dim index = 0
    25. For i = Anzahl To Rest + 1 Step -1
    26. index += Modulo - 1 ' Korrektur für das herausgenommene Element
    27. While index >= i ' Index-Begrenzung
    28. index -= i
    29. End While
    30. ll.RemoveAt(index) ' Sä sollen säch sätzen
    31. Next
    32. Return ll
    33. End Function
    34. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @nogood: Ich denke, eine Schleife wäre hier besser als eine (End-) Rekursion.
    Bei dir wird ja für jeden Durchlauf eine neue List(Of Person) gebildet, mit zwischen 3 und 1000 Elementen. Diese Listen werden alle im Speicher festgehalten, während sich die Rekursion immer weiter vertieft.
    Bei 1 Mio Elementen könnte das ungemütlich werden - stell ich mir vor.
    Auch geht bei 1Mio Elementen der Rekursions-Stack ziemlich hoch - kann ich nicht ausrechnen. Jedenfalls mit jeder Runde wird die Elemente-Zahl ja um 1/7 verringert - weiss nicht, wieviele Runden das bei 1Mio ergibt.
    Jedenfalls pro Runde ein Selbst-Aufruf, also Erhöhung des Rekursions-Stacks.
    Ich weiss nicht, wie gross der werden kann, aber iwann gibts den berühmten StackOverflow.

    In einer Schleife hingegen würden die nicht mehr gebrauchten Listen automatisch weggeworfen, wenn eine neue Liste an dieselbe Variable zugewiesen wird.

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @Benutzername Gib mal eine Rückmeldung, egal welchen Code Du genommen hast ob Du ihn bei dir so zum laufen bekommst, dass alles i.O. ?
    Geht jetzt die Diskussion eher ums Verstehen oder kämpfst Du "immer noch" mit VS etc.

    @Benutzername ich bin hier eher auch neu! Hör lieber auf @VaporiZed @ErfinderDesRades @RodFromGermany und alle anderen mit deutlich mehr wissen als ich.



    @ErfinderDesRades Ist das wirklich der Fall, dass die Listen immer noch im Stack gehalten werden? Gebraucht werden Sie nicht mehr. Es ist ein Loop das sich mit einer "neuen" Liste selbst aufruft. Die alte Liste wird in dem Moment des Rücksprunges nicht mehr benötigt.

    Liste (1000) rein -> neue Liste mit 850 noch stehenden Personen entsteht -> jetzt erfolgt der Aufruf der selben Funktion eben mit dieser Liste. Die Liste mir 1000 kann/ist weg.
    NochStehendePersonen = New List(Of Person)() steht in der Methode drin und diese Liste wird wieder und wieder neu gefüllt mit immer weniger Personen und zum aufrufen der Methode benutzt.
    (Eventuell ist de Begriff Rekursion falsch, aber da fehlt mir das theoretische Wissen; Rekursion ist bei mir im Moment so def. das eine Methode sich immer wieder selbst aufruft. In diesem Fall ist es aber nicht, so dass immer ein neues genestetes Loop im Loop im Loop ... entsteht)

    ---------------------
    Deine Meinung hat natürlich Gewicht für mich.

    Ich bin immer noch eher froh wenn mein Code endlich fehlerfrei kompiliert und das rauskommt was ich erwarte ... mehr Wissen hab ich nicht (Lebensdauer Speicher Stack garbge collector etc. Value vs Ref muss ich noch immer mal wieder nachsehen).

    Ich hatte ja 1 Mio Personen probiert in Post 25 steht die Zeit. Eben auch noch mal für 10 Mio. probiert ging in ca 2 Sek. (aber mit dem orig. C# Code der ganz ein bissel anders ist).
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nogood“ ()

    nee - du hast recht - die Listen werden entsorgt. NochStehendePersonen wird ja nicht lokal erstellt in der Play()-Methode, sondern NochStehendePersonen ist eine Modul-Variable, und wird somit in post#44, zeile#29 immer überschrieben (wodurch die vorherige dem GC anheimfällt).

    Eine Rekursion ists aber dennoch, deine def. davon ist richtig: Die Methode ruft sich selbst auf.
    EndRekursion ists deshalb, weil der Selbst-Aufruf ganz am Ende steht, bevor die Methode returnt.

    EndRekursion braucht man eiglich nur in Sprachen, die keine Schleifen kennen, wie glaub f# - habich mal gehört.
    Eine EndRekursion ist relativ einfach in eine SchleifenForm zu transformieren:

    VB.NET-Quellcode

    1. 'aus
    2. Private Sub Play(ByVal personen As List(Of Person))
    3. If personen.Count() <= 3 Then
    4. Return
    5. End If
    6. NochStehendePersonen = New List(Of Person)()
    7. For Each p As Person In personen
    8. CounterStehender += 1
    9. If CounterStehender <> 7 Then
    10. NochStehendePersonen.Add(p)
    11. End If
    12. If CounterStehender = 7 Then
    13. CounterStehender = 0
    14. End If
    15. Next
    16. Play(NochStehendePersonen)
    17. End Sub
    18. 'wird
    19. Private Sub Play(ByVal personen As List(Of Person))
    20. Do
    21. If personen.Count() <= 3 Then
    22. Return
    23. End If
    24. NochStehendePersonen = New List(Of Person)()
    25. For Each p As Person In personen
    26. CounterStehender += 1
    27. If CounterStehender <> 7 Then
    28. NochStehendePersonen.Add(p)
    29. End If
    30. If CounterStehender = 7 Then
    31. CounterStehender = 0
    32. End If
    33. Next
    34. personen = NochStehendePersonen
    35. Loop
    36. End Sub
    37. 'daraus wiederum könnte werden:
    38. Private Sub Play(ByVal kandidaten As List(Of Person))
    39. Do
    40. If kandidaten.Count() <= 3 Then Return
    41. NochStehendePersonen = New List(Of Person)()
    42. For Each p As Person In kandidaten
    43. CounterStehender += 1
    44. If CounterStehender < 7 Then NochStehendePersonen.Add(p) Else CounterStehender = 0
    45. Next
    46. kandidaten = NochStehendePersonen
    47. Loop
    48. End Sub

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @nogood
    Deinen überarbeiteten Code aus Beitrag Nr. 44 kann ich nachvollziehen, da sich dieser - was die verwendeten Befehle angeht - ungefähr auf meinem bisherigen Kenntnisstand befindet. Zumindest was das Verständnis angeht. Das ganze eigenständig Programmieren, da muss ich nach wie vor passen. Vielleicht schaue ich ja in 3-4 Wochen nochmal zurück und werfe mit Codes nur so um mich.
    Also long story short, ich kämpfe immer noch :D

    Aber ich werde wohl vom guten Josephus erstmal Abstand nehmen. Ich habe aber die Befürchtung, dass ich mich in den kommenden Tagen nochmals hier im Forum melden werde mit weiteren Verständnisproblemen...

    Edit: falls es doch Mitleser aus meinem Kurs hier gibt, denkt daran, dass identische Abgaben gleich rausfliegen also versucht es erst gar nicht :P

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Benutzername“ ()

    Ich bin mir sicher, das es eine wenn auch vielleicht kleinere Gemeinschaft gibt, die immer gerne solche Aufgaben löst.

    Also jederzeit melden, wenn es dir danach ist.

    Hier ist noch meiner den ich gemacht habe. Ich weiss zwar nicht wie schnell der ist, aber vielleicht habe ich glück und der Algo kommt auch an solche Werte wie die von @nogood.

    Ist in der Konsole gemacht, und sollte genau das machen, was er muss. Ich hoffe die Zahlen stimmen, da der Vergleich ein bisschen fehlt.

    SpecialPermutation

    C#-Quellcode

    1. using System;
    2. using System.Linq;
    3. using System.Diagnostics;
    4. namespace JosephusCs
    5. {
    6. class Program00
    7. {
    8. public static void Main()
    9. {
    10. int k = 7;
    11. int count = 3;
    12. int n = 10_000_000;
    13. Console.WriteLine($"n = {n}, k = {k}, cnt = {count}");
    14. //Ähnlich aber nicht Josephus
    15. SpecialPerm(n, k);
    16. Console.ReadLine();
    17. }
    18. private static void SpecialPerm(int n, int k)
    19. {
    20. var sw = Stopwatch.StartNew();
    21. var result = SpecialPermutation(n, k);
    22. Console.WriteLine($"t = {sw.ElapsedMilliseconds} ms");
    23. Console.WriteLine();
    24. Enumerable.Range(0, result.Length).ToList()
    25. .ForEach(x => Console.Write($"{result[x]} "));
    26. Console.WriteLine();
    27. }
    28. private static int[] SpecialPermutation(int n, int k)
    29. {
    30. int it = 1;
    31. int persnr = k;
    32. if (n <= 1) return new[] { n };
    33. // Bei dieser Variante wird der Sitzende mitgezählt, und die
    34. // Array wird wiederum zirkular duchlaufen.
    35. // Wenn z.B. Personenanzahl n = 1000 und der k = 7 teilerfremd
    36. // zueinander sind, dann werden immer alle Teilnehmer sich setzen.
    37. // In diesem speziellen Fall, Resultat = 0 bzw. alle Personen im
    38. // Kreis sitzen.
    39. // Wenn sie nicht teilerfremd sind, wird irgendwann ein
    40. // Sitzender nochmals gebeten zu sitzen, nur das geht nicht
    41. // mehr, also wird abgebrochen. Resultat >= 0
    42. // Ist ein sehr wichtiger Algorithmus um z.B. die Schlüsseldurchläufe
    43. // in der Kroyptographie zu verändern. D.h. Statt den Schlüssel
    44. // iterativ mit Step = 1 zu durchlaufen, wird ein Step > 1 hinzugefügt.
    45. // Bei Rückläufen sind die Step-Werte dann einfach kleiner 0.
    46. // Es werde natürlich nur Werte verwendet die teilerfremd zueinander sind,
    47. // damit der Schlüssel immer vollkommen durchlaufen werden kann.
    48. // Dieser Algo entspricht auch einer Permutation, denn es werden bei
    49. // Teilerfremdheit alle Plätze in eine andere Anordnung gebracht.
    50. // (Plätze werden vertauscht wie bei einer Transposition)
    51. var place = new int[n];
    52. while (true)
    53. {
    54. if (place[(persnr - 1) % place.Length] != 0 || it > place.Length)
    55. break;
    56. place[(persnr - 1) % place.Length] = it;
    57. it += 1;
    58. persnr += k;
    59. }
    60. if (it > place.Length) return place;
    61. // Ist 0-basierend darum korrekter Wert >> Index (i) + 1
    62. return place.Select((x, i) => x == 0 ? i + 1 : -1)
    63. .Where(i => i != -1).ToArray();
    64. }
    65. }
    66. }

    Josephus Iterativ

    C#-Quellcode

    1. using System;
    2. using System.Linq;
    3. using System.Diagnostics;
    4. namespace JosephusCs
    5. {
    6. public class Program01
    7. {
    8. public static void Main()
    9. {
    10. int k = 7;
    11. int count = 3; //Wenn 0 >> Ganzer Kreis ausgeben
    12. int n = 1_000_000;
    13. if (count == 0 && n > 20)
    14. n = 20;
    15. Console.WriteLine($"n = {n}, k = {k}, cnt = {count}");
    16. var sw = Stopwatch.StartNew();
    17. var result = JosephusIterativ(n, k, count);
    18. Console.WriteLine($"t = {sw.ElapsedMilliseconds} ms");
    19. Console.WriteLine();
    20. Enumerable.Range(0, result.Length).ToList()
    21. .ForEach(x => Console.Write($"{result[x]} "));
    22. Console.WriteLine();
    23. Console.ReadLine();
    24. }
    25. private static int[] JosephusIterativ(int n, int k, int cnt)
    26. {
    27. if (n < 2) return new[] { n };
    28. //Kleiner Nachteil: Bei grossen k-Werten, wird wiederum
    29. //immer wieder durch alle Teilnehmer iteriert, was den Algo
    30. //quasi nicht zum Abschluss bringen möchte. Daher hier eine
    31. //Performenceeinbusse.
    32. var it = 0;
    33. var kiter = k;
    34. var setter = 0;
    35. var iteration = (k - 1) % n;
    36. var place = new int[n];
    37. var result = new int[cnt];
    38. while (true)
    39. {
    40. if (setter >= n) //Abbruchbedingung
    41. break;
    42. if (kiter == k && place[iteration] == 0)
    43. {
    44. setter += 1;
    45. place[iteration] = setter;
    46. if (setter > n - cnt)//Füllen der letzten Werte
    47. result[it++] = iteration + 1;
    48. kiter = 0;
    49. }
    50. if (kiter != 0 && place[iteration] != 0)
    51. kiter -= 1;
    52. kiter += 1;
    53. iteration += 1;
    54. if (iteration == n)
    55. iteration = 0;
    56. }
    57. if (cnt == 0) return place;
    58. return result;
    59. }
    60. }
    61. }

    WIKI-Test

    C#-Quellcode

    1. using System;
    2. using System.Diagnostics;
    3. namespace JosephusCs
    4. {
    5. class WikiTest00
    6. {
    7. public static void Main()
    8. {
    9. TestWIKI(10, 7, 1000);
    10. TestWIKI_K2(10, 1000);
    11. }
    12. static void TestWIKI(int n, int k, int cnt)
    13. {
    14. for (int i = 0; i < cnt; i++)
    15. {
    16. var r1 = JosephusIterativ(n, k, 1);
    17. var r2 = JosephusWIKI3(n++,k);
    18. Debug.Assert(r1[0] == r2);
    19. }
    20. }
    21. static void TestWIKI_K2(int n, int cnt)
    22. {
    23. var k = 2;
    24. for (int i = 0; i < cnt; i++)
    25. {
    26. var r1 = JosephusIterativ(n, k, 1);
    27. var r2 = JosephusWIKI2(n);
    28. var r3 = JosephusWIKI(n++);
    29. Debug.Assert(r1[0] == r2);
    30. Debug.Assert(r1[0] == r3);
    31. }
    32. }
    33. static int JosephusWIKI(int n)
    34. {
    35. if (n == 1)
    36. return 1;
    37. if ((n % 2) == 0)
    38. return 2 * JosephusWIKI(n / 2) - 1;
    39. if ((n % 2) == 1)
    40. return 2 * JosephusWIKI((n - 1) / 2) + 1;
    41. return default;
    42. }
    43. static int JosephusWIKI2(int n)
    44. {
    45. var m = Math.Floor(Math.Log(n, 2));
    46. var l = n - Math.Pow(2, m);
    47. var j = 2 * l + 1;
    48. return (int)j;
    49. }
    50. static int JosephusWIKI3(int n, int k)
    51. {
    52. if (n <= 1) return n;
    53. return (JosephusWIKI3(n - 1, k) + k - 1) % n + 1;
    54. }
    55. private static int[] JosephusIterativ(int n, int k, int cnt)
    56. {
    57. if (n < 2) return new[] { n };
    58. var it = 0;
    59. var kiter = 0;
    60. var setter = 1;
    61. var iteration = (k - 1) % n;
    62. var place = new int[n];
    63. var result = new int[cnt];
    64. place[iteration] = setter;
    65. while (true)
    66. {
    67. if (setter >= n)
    68. break;
    69. if (kiter == k && place[iteration] == 0)
    70. {
    71. setter += 1;
    72. place[iteration] = setter;
    73. if (setter > n - cnt)
    74. result[it++] = iteration + 1;
    75. kiter = 0;
    76. }
    77. if (kiter != 0 && place[iteration] != 0)
    78. kiter -= 1;
    79. kiter += 1;
    80. iteration += 1;
    81. if (iteration == n)
    82. iteration = 0;
    83. }
    84. if (cnt == 0) return place;
    85. return result;
    86. }
    87. }
    88. }

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    @ErfinderDesRades Ich hab jetzt nochmal Zeit gehabt mir deine Lösung mit dem Do Loop anzusehen. Danke für das teilen! Die LSG ist noch besser :) Ich freue mich über den Austausch.

    @Benutzername Viel Erfolg mit der HA und ich denke, dass sich einige freuen wenn es neuen Knobelstoff gibt.
    codewars.com Rank: 4 kyu