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.

    VB.NET Josephus Problem, blutiger Anfänger

    Guten Tag,

    ich setze mich nun die dritte Woche mit Programmieren auseinander. Zum Einsatz kommt Visual Basic und ich bin bisher eher überfordert, da meine Kenntnisse und mein Vokabular praktisch noch bei 0 sind. Computeraffinität ist definitiv vorhanden aber ich habe mir das ganze einfacher vorgestellt. Gefühlt sind auch nur 0,1 % aller Tutorials zu Visual Basic. Hilft ja alles nix ;)

    Die Problemstellung lautet wie folgt:
    1000 Leute im Kreis, jeder siebte setzt sich hin. Welche drei Leute bleiben am Ende stehen?

    Ich habe bisher rausgefunden, dass es sich hier um das Josephus Problem handelt und habe diverse Erklärvideos zum Problem angeschaut und kann dem soweit auch folgen. Einen Code zu diesem Problem habe ich auch gefunden allerdings kann ich damit nicht wirklich was anfangen, da hier u.a. soweit ich das erkennen konnte eine Subroutine zum Einsatz kommt, mit der ich mich erst diese bzw. nächste Woche erstmalig beschäftigen werde.

    Nun bin ich aber noch nicht in der Lage, das alles auch in einen Code zu übersetzen. Das ganze soll in einer Console ausgegeben werden und im Anschluss in weiteren Teilaufgaben noch angepasst werden (bspw. soll die Anzahl der Leute sowie der Abstand von Hand eingegeben werden können).

    Ich erwarte selbstverständlich keine Musterlösung aber ich muss ganz ehrlich sagen, ich sehe den Wald vor lauter Bäumen nicht. Womit fange ich denn an? Was ist der erste Schritt?
    Ich hatte gedacht ich brauche auf jeden Fall erstmal zwei Variablen,

    Quellcode

    1. ​Dim n as Integer
    2. Dim i as Integer

    n als Anzahl der Personen und i als "Zahl bis zu der ich zähle". Und die einzelnen Iterationen laufen dann mittels einer "Do-Until-Schleife" ab (meiner Vorstellung nach "Do [zähle durch in 7er Schritten] Until [bis die finalen 3 Leute stehen bleiben])

    Über eine kleine Starthilfe würde ich mich sehr freuen

    Grüße

    Benutzername schrieb:

    1000 Leute im Kreis, jeder siebte setzt sich hin. Welche drei Leute bleiben am Ende stehen?

    hmm - in meiner Welt, wenn sich da von 1000 leuten jeder 7. hinsetzt, da bleiben 1000-1000/7 leute stehen, also wohl mehr als 700! (bin schlecht im Kopfrechnen)

    Aber was du auf jeden Fall schoma machen kannst - dein Programmiersystem korrekt einstellen, sodass Vb.Net bei dir auch wirklich eine objektorientierte Sprache ist:
    Visual Studio - Empfohlene Einstellungen

    Vb.Net wird nämlich nicht als objektorientierte Sprache ausgeliefert, und je früher man das nachbessert, desto weniger Ärger handelt man sich ein.
    Oder lern c# - da wird kein son Unfug getrieben.



    Also ich habs mir überlegt: Bei dir setzen sich jeder 7. immer wieder hin, richtig? Sowas muss aber gesagt werden inne Aufgabenstellung.
    Ja, also die Frage ist: Welche bleiben stehen?
    Gegenfrage: Kennst du all ihre Namen? Oder wie soll man jemals sagen können, welche stehen bleiben?



    Ich hab ja immer sone Macke mittm Datenmodell. Jedes Problem will ich in einem Datenmodell nachgebildet haben - dann geht die Lösung meist hopphopp.
    Also dein Problem sind Leute, und die müssen einen Namen haben, und die müssen entweder Stehen oder sitzen.
    Das sind die für dieses Problem wichtigen Eigenschaften.
    Also musst du eine Klasse bauen, die diese beiden Eigenschaften hat, und davon dann 1000 Objekte erstellen und in eine Liste tun.
    Dann kannste in einer Schleife immer wieder jeden 7. auf "hingesetzt" stellen - dann wirste ja sehen, wer am Ende stehen bleibt.

    Aber wenn du noch nichtmal bei SubRoutinen (in vb heisst das "Methode") angekommen bist, dann wirst du auch wohl noch keine Klasse kennen.
    Jo, weiss ich mal wieder nicht, was das soll - welcher Idiot stellt solche Aufgaben?

    Hier mal die Klasse Person, mit der ich das Problem angehen würde:

    VB.NET-Quellcode

    1. Public Class Person
    2. Public Nummer As Integer
    3. Public Sitzt As Boolean
    4. End Class
    Statt eines Namen gebe ich den Personen nur eine Nummer - dassis einfacher.
    Und davon kann man nun 1000 in eine Liste tun.
    Oder meinetwegen in ein Array - von Listen wirste auch noch nix gehört haben:

    VB.NET-Quellcode

    1. Dim Personen(999) As Person
    2. For i = 0 To 999
    3. Personen(i) = New Person With {.Nummer = i, .Sitzt = False}
    4. Next
    Damit kann man nun Schleifen schreiben, wo sich jeder 7. immer hinsetzt.

    Jetzt aber genug vorgesagt.

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

    Nachdem die ersten 1000 Leute durchgezählt haben, beginnt das Durchzählen wieder von neuem. Diese Info habe ich noch vergessen. Ich dachte, diese Aufgabe ist eine gängige Anfänger Aufgabe.

    ErfinderDesRades schrieb:

    Oder lern c# - da wird kein son Unfug getrieben.

    Wenn es nur so einfach wäre. Hier habe ich leider keinen Spielraum. Die settings werde ich mal durchgehen, danke für den Tipp.


    Ich muss auch wieder editieren, Doppelposts sind wohl nicht möglich.
    Erst einmal vielen Dank für die Antwort um diese Uhrzeit noch.

    Ich bin ebenfalls aus Zufall auf ein weiteres Erklärvideo gestoßen, in der ebenfalls die Idee mit einer Liste erwähnt wurde. Werde mir deinen Vorschlag mal genauer ansehen. Danke!

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

    Ja, mach mit Liste - Array ist blöd dafür - du musst die hingesetzten ja aus der Liste entfernen - das kann Array nicht - also Code-Korrektur:

    VB.NET-Quellcode

    1. Public Class Person
    2. Public Nummer As Integer
    3. Public Sitzt As Boolean
    4. End Class
    5. '...
    6. '...
    7. Dim Personen As New List(Of Person)
    8. For i = 0 To 999
    9. Dim pers = New Person With {.Nummer = i, .Sitzt = False}
    10. Personen.Add(pers)
    11. Next
    Also jetzt ist Personen eine Liste, und eine Liste hat (im Gegensatz zu Array) eine Add()-Methode (wie du siehst), und hat auch eine .Remove()-Methode, die du hier nicht siehst, die du aber evtl. brauchen wirst.
    @Benutzername Schöner Benutzername, willkommen im Forum. :thumbup:
    Ich versuche mal, das Problem algorithmisch zu formulieren:
    In einer List(Of Integer), die initial mit {1, 2, ..., 1000 } befüllt ist, soll zirkular so lange jedes siebente Element entfernt werden, bis nur noch drei Elemente enthalten sind.
    Welche?
    ====
    So. Mit ein klein Wenig Erfahrung solltest Du nun das Problem perfekt lösen können.
    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!
    @exc-jdbi Falsche Herangehensweise, das wird durch das "zirkular" aufgehoben.
    Du hast einen Kreis mit 1000 Zellen.
    Wenn Du die 7. Zelle raus nimmst, hat er nur noch 999 Zellen
    und
    Du nimmst dann die 14. Zelle raus, hat er nur noch 998 Zellen
    und
    Du nimmst dann die 21. Zelle raus, hat er nur noch 997 Zellen
    usw.
    Wenn Du bei einer Zelle mit einem Wert über 993 bist, musst Du bei Index 0 weiter machen.
    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!
    @exc-jdbi Hat er im zweiten Post geschrieben.

    Benutzername schrieb:

    Ich dachte, diese Aufgabe ist eine gängige Anfänger Aufgabe.
    Nicht denken, sondern stets die Frage bzw. das Problem so präzise wie möglich beschreiben :!:

    Benutzername schrieb:

    Nachdem die ersten 1000 Leute durchgezählt haben, beginnt das Durchzählen wieder von neuem. Diese Info habe ich noch vergessen.
    @Benutzername Bleibt die Frage:
    Wenn ich bei Index (nicht Inhalt) (Maximum - 2) gelandet bin,
    fahre ich dann fort bei Index 0 oder bei Index 5 :?:
    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!
    Ich sage ja nicht das es falsch ist.

    Es ist nur nicht in der Aufgabenstellung #1 und #3 erwähnt.

    Und ich denke bei solchen Aufgabenstellungen meistens ein bisschen weiter (versuche es mindestens), was bestimmt nicht falsch ist. Wer es oberflächlich mag, der soll wie du sagst "Nicht denken".

    Freundliche Grüsse

    exc-jdbi
    Kleiner Zwischeneinwurf: War das nicht so ne römisch-christliche Geschichte, bei der 40 Christen in ner Höhle sitzen und der (damals noch) Sektenführer sagte: »Die Römer nehmen uns bald fest. Jetzt bilden wir einen Kreis und zählen durch. Jeder 7. bringt sich um. Danach wird mit den restlichen von vorn mit zählen begonnen.« Am Ende blieb ganz zufällig der Sektenführer übrig und brachte sich nicht um.
    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.
    Ja ist die Geschichte von Flavius Josephus der sich bei den Römer mit seinem letzten Kumpan ergeben hat.

    Ich hab die Geschichte auf Wiki durchgelesen über Mittag, weil den Algo hab ich nicht gekannt nach Namen. Nicht einmal die Geschichte.

    Den Algo hab ich jetzt kurz geschrieben. Nachdem man die Geschichte kennt, kennt man auch das Verfahren, was dahinter steht. Von dem wollte ich ja heute Morgen mehr erfahren, ohne ein Resultat, denn auf Wiki steht schon eine Lösung. Sie reicht zwar nicht ganz um das obige Problem zu lösen, aber es zeigt eine Möglichkeit wie man auf den letzten Wert kommt.

    Freundliche Grüsse

    exc-jdbi
    @Benutzername Achtung Service kommt (leider aber wie immer mit ein paar Haken und Ösen)! Code ist in C# man kann jedoch hier C#Code in VBCode umwandeln.
    Schau dir zuerst das .gif am Ende des Posts an - dann versuch dir den Code der Klasse Person anzusehen und dann erst den Codeblock.



    In Visual Studio ein Winforms Net.Framework Projekt erstellen
    -jetzt in die Form1 per Toolsbox folgendes hinzufügen 1x Button 1xRichtextbox 1xDatagridview (und diese wie im folgenden Code umbenennen (muss Du machen sonst geht es nicht)
    // Richtexbox auf die Form ziehen und rechts den Namen der Richtextbox unter Name ändern ->Button1= BtnStartRound, Richtextbox1=RtxbxInfo, Datagridview1=DgvPersonenkreis etc.)
    -dann in C# mit F7 den Quellcode von From1 aufrufen den folgenden Code einfügen (also alles was da steht löschen und dann kompletten Code einfügen)




    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Drawing;
    6. using System.Linq;
    7. using System.Text;
    8. using System.Threading.Tasks;
    9. using System.Windows.Forms;
    10. namespace WF_JosephusProblem
    11. {
    12. public partial class Form1 : Form
    13. {
    14. //Deine "Variablen"
    15. readonly int AnzahlPersonen = 20;
    16. readonly int Teiler = 7;
    17. readonly int Schluss = 3;
    18. int CounterStehendePerson = 0;
    19. int RundenAnzahl = 0;
    20. int RundenCounterStehende = 0;
    21. //Liste von Objekten der Klasse/Bauplans Person
    22. readonly List<Person> LstPersonen = new List<Person>();
    23. public Form1()
    24. {
    25. //automatisch gernerierte Methode von WinForms
    26. InitializeComponent();
    27. //Liste(0)= Person(1, steht=true, sitzt=false)
    28. //Liste(1)= Person(2, steht=true, sitzt=false)
    29. //...
    30. for (int i = 1; i <= AnzahlPersonen; i++)
    31. {
    32. LstPersonen.Add(new Person(i));
    33. }
    34. }
    35. //Methode die ausgeführt wird nach Knopfdruck (ButtonPress/Click)
    36. //im Hauptfenster
    37. private void BtnStartRound_Click(object sender, EventArgs e)
    38. {
    39. RundenCounterStehende = 0;
    40. foreach (var person in LstPersonen)
    41. {
    42. if (person.PersonSteht)
    43. {
    44. CounterStehendePerson += 1;
    45. }
    46. if (person.PersonSteht && CounterStehendePerson == Teiler)
    47. {
    48. person.PersonSetztSichHin();
    49. CounterStehendePerson = 0;
    50. }
    51. if (person.PersonSteht)
    52. {
    53. RundenCounterStehende += 1;
    54. }
    55. }
    56. //Ende der Runde -> update UI UserInterface
    57. RundenAnzahl += 1;
    58. //DataGridView siehe ToolLeiste
    59. //Zuteilung was das Datagriedview anzeigen soll
    60. DgvPersonenkreis.DataSource = LstPersonen;
    61. //im Textfenster sollen Infos angezeigt werden
    62. //Anzahl Runden, wieviele stehen noch etc.
    63. RtxbxInfo.Text += $"Runde: {RundenAnzahl:d2} \t\t Stehende: {RundenCounterStehende} \n";
    64. DgvPersonenkreis.Refresh();
    65. //Ende des "Spiels"
    66. if (RundenCounterStehende <= Schluss)
    67. {
    68. foreach (var person in LstPersonen)
    69. {
    70. if (person.PersonSteht)
    71. {
    72. RtxbxInfo.Text += $"\nPerson Nr.: {person.Id} steht noch! \n";
    73. }
    74. }
    75. //Button/Knopf disabled stellen Spiel ist vorbei (grau hinterlegen)
    76. BtnStartRound.Enabled = false;
    77. }
    78. }
    79. }
    80. }


    Jetzt fehlt dir noch die Klasse Person.cs (oder eben .vb). Eine Klasse dem Projekt hinzufügen kann man mit rechter Maustaste auf deinen Projektnamen (rechte Seite in VisualStudio ProjektmappenExplorer // siehe Screenshot).
    Der Name der Klasse sollte Person sein.

    Jetzt noch den folgenden Quellcode in die Klasse kopieren und es könnte laufen?!

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading.Tasks;
    6. namespace WF_JosephusProblem
    7. {
    8. public class Person
    9. {
    10. //Eigenschaften eines Objektes der Klasse Person
    11. public int Id { get; set; }
    12. public bool PersonSteht { get; set; }
    13. public bool PersonSitzt { get; set; }
    14. //Methode der Klasse/Bauplan Person
    15. public void PersonSetztSichHin()
    16. {
    17. PersonSteht = false;
    18. PersonSitzt = true;
    19. }
    20. //Personenkonstruktor
    21. //das wird gemacht wenn nach "Bauplan" der Klasse Person ein Objekt erzeugt wird
    22. //erzeuge ein Objekt der Klasse Person mit folgenden Eigenschaften:
    23. //Id = die Übergbene Zahl // PersonSteht= true // PersonSitzt= false
    24. public Person(int id)
    25. {
    26. Id = id;
    27. PersonSteht = true;
    28. PersonSitzt = false;
    29. }
    30. }
    31. }


    :) :) :) fertig !! Viel Spaß beim rumspielen ... falls es irgendwie geht fang früh an Klassen zu benutzen, dass Spiel hier ist ein super Start um das Prinzip zu lernen.
    Bilder
    • Untitled.gif

      208,75 kB, 276×800, 93 mal angesehen
    • Bild_2020-12-04_175240.png

      60,25 kB, 920×891, 67 mal angesehen
    • vbhelp.jpg

      390,48 kB, 1.548×1.115, 62 mal angesehen
    codewars.com Rank: 4 kyu

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

    Ich bin überrascht, dass meine Problemstellung an der ich verzweifle doch den/die ein oder andere interessiert :D

    Danke vielmals für die Rückmeldungen. Ich muss das alles erstmal nach und nach verarbeiten...

    Ich habe gesehen, dass in in Antwort 4 von ErfinderDesRades in einer separaten Public Class zunächst "Person" jeweils "Nummer" und "Sitzt" als Integer bzw. Boolean deklariert wurden. Nun habe ich in einem Video zu Listen gesehen, dass der Teil in Klammern des Befehls

    VB.NET-Quellcode

    1. Dim Personen As New List(Of Person)

    eigentlich den Datentyp der Elemente in der Liste festlegen (also Integer, String usw.)

    VB.NET-Quellcode

    1. ​Dim Personen As New List(Of Person)

    erzeugt mir ja eine neue Liste mit dem Namen "Personen". Nun sind da ja aber nicht einfach nur Zahlen wie 1, 2, 3, ... enthalten sondern "Person".

    Nun reicht mein Hirnschmalz noch nicht aus um mir vorstellen zu können was hier eigentlich passiert. Ist "Person" jetzt ein Datentyp? Ne oder ?(

    Sorry, keine großen Fortschritte ich weiß...

    Benutzername schrieb:

    Ist "Person" jetzt ein Datentyp?
    Ja.
    Eine Klasse oder eine Struktur mit dem Namen Person.
    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: Das Konzept der Runden hat bei dem Problem keine Relevanz. Es ist nur relevant, dass jeder 7. sich setzt alias stirbt. Der Kreis an sich ist nur zum einfachen Weiterzählen da. Wieviele Runden absolviert werden, spielt keine Rolle, nur wer am Ende übrig bleibt, ist wichtig.
    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.
    Was genau passiert hier nach dem ersten =-Zeichen?

    VB.NET-Quellcode

    1. Dim pers = New Person With {.Nummer = i, .Sitzt = False}


    Eine neue Variable "pers" wird deklariert aber den Rest habe ich so noch nicht gesehen.

    Meine Überlegung:
    Für jede Person i von 0 bis 999 (da die 0 mitgezählt wird sind es 1000 Personen, richtig?) wird ein Element "Person" angelegt. Jedes dieser Elemente wird fortlaufend und aufsteigend nummeriert (.Nummer = i) und bekommt erstmal den "Status", dass die zugehörige Person gerade steht (.Sitzt = False)

    VB.NET-Quellcode

    1. Personen.Add(pers)

    fügt jede Variable pers, die mit den ganzen Informationen von ebene ausgestattet wurde, der Liste Personen hinzu?

    Möglicherweise verwende ich den ein oder anderen Fachbegriff an der falschen Stelle.

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

    Die 0-basierte Liste mag am Anfang ein bisschen fremd wirken. Hat aber den Vorteil das Zirkular gearbeitet werden kann.

    Den Rest hast quasi schon selber beschrieben. pers wird mit der vorgebenen Klasse initialisiert, wobei der Wert der Nummer immer um 1 hochgezählt wird.
    Also zur Versinnbildlichung, innerhalb einer Klasse kann ich diverse Informationen hinterlegen (bspw. das Outfit einer Person von Kopf bis Fuß in Form und Farbe). Wenn ich jetzt wegen mir 10 verschiedene Outfits habe, gibt es auch 10 Klassen.
    Nun kann ich einzelnen Personen i ein bestimmtes Outfit zuweisen, indem ich sie mit der entsprechenden Klasse initialisiere?
    Die Klasse ist wie ein Bauplan für eine Vorlage. Wie du beschrieben hast, kannst du dem Outfit gewünschte Eigenschaften zuweisen. Für die Instanzierung wird dann einfach die Klasse (der Bauplan) herangezogen. Es ergeben sich in deinem Falle 10 Instanzen von der gleichen Klasse (oder vom gleichen "Bauplan"), dessen Eigenschaften mit einer Initialisierung definniert werden können.