Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Denkanstoß: Brauche gewichtete "Zufallszahlen" (https://www.delphipraxis.net/103811-denkanstoss-brauche-gewichtete-zufallszahlen.html)

guidok 22. Nov 2007 06:31

Datenbank: NexusDB • Zugriff über: NexusDB

Denkanstoß: Brauche gewichtete "Zufallszahlen"
 
Hm, ich brauche mal einen kleinen Denkanstoß für einen Vokabeltrainer.

Problem:

-Vokablen sollen aus einer DB zufällig abgefragt werden.
-Es soll für jede Vokabel einen "Übungslevel" geben.
-Wird eine Vokabel richtig übersetzt dann steigt der Übungslevel
-Wird eine Vokabel falsch übersetzt dann fällt der Übungslevel
-Vokabeln mit niedrigem Übungslevel werden öfter abgefragt
-Vokabeln mit hohem Übungslevel werden seltener abgefragt

Also so eine Art "Lernen mit Karteikasten".

Gesucht ist nun eine elegante Methode dies softwaretechnisch umzusetzen.

-Ich möchte idealerweise bei richtiger oder falscher Antwort einfach etwas addieren oder subtrahieren müssen (innerhalb einer Bereiches natürlich)
-Ich möchte per SQL-Abfrage (darum in der Spalte Datenbank) eine zufällig bestimmte Vokabel mit der richtigen Häufigkeit abrufen können (möglichst simpel).

Die Tabelle stelle ich mir ungefähr so vor:

USER INT //für eine Benutzer-ID, da für mehrere Benutzer mit eigenen Vokabeln
LANG INT //für eine Sprach-Kennung, da für mehrere Sprachen offen
NATIVE VARCHAR //das Wort in der Muttersprache
FOREIGN VARCHAR //das Wort in der Fremdsprache
LEVEL INT //der Übungslevel
LAST DATE //Datum der letzten Abfrage

Für die gewichtete Zufallszahl dachte ich mir einen Bereich festzulegen, z.B. 1-14

1-5 = Level 1
5-8 = Level 2
9-11 = Level 3
12-13 = Level 4
14 = Level 5

Damit sollte ich Vokabeln im Level 1 öfter zufällig ausgewählt bekommen, als eine Vokabel im Level 5.

Ich kann dann zwar bei richtiger Antwort einfach addieren, bis 14 erreicht ist, wenn ich aber diesen Wert in der DB speichere, dann müsste ich bei der SQL-Abfrage für eine Vokabel im Level 1 beispielsweise schreiben WHERE LEVEL=1 OR LEVEL=2 OR LEVEL=3 OR LEVEL=4 OR LEVEL=5. Finde ich jetzt nicht elegant. Das geht bestimmt besser.

Hat jemand eine Idee?

Gruß,
Guido

alzaimar 22. Nov 2007 06:58

Re: Denkanstoß: Brauche gewichtete "Zufallszahlen"
 
Gewichtete Zufallszahlen, Beispiel:

Die 1 soll mit der Gewichtung 3 gezogen werden (Gw(1) = 3), Gw(2)=1, Gw(3)=5 und Gw(4)=2.

Du erstellst Dir ein Array [0.. 3+1+5+2 - 1] of Integer und füllst 3x die 1, 1x die 2, 5x die 3 und 2x die 4.

A = (1,1,1,2,3,3,3,3,3,4,4)

Nun ziehst du zufällig irgendeine Zahl aus dem Array und -bupps- hast Du deine gewichteten Zufallszahlen.

Reinhardtinho 22. Nov 2007 08:35

Re: Denkanstoß: Brauche gewichtete "Zufallszahlen"
 
Hallo,

ein allgemeiner Ansatz für Ziehungen mit unterschiedlicher Wahrscheinlichkeit ist die Monte-Carlo-Simulation (oder so ähnlich / ich hoffe ich habe nich den falschen Link rausgesucht).

Dabei werden die Wahrscheinlichkeiten aufsummiert.

Beispiel:
Die Zahl 1 kommt mit einer Wahrscheinlichkeit mit 25 %.
Die Zahl 2 kommt mit einer Wahrscheinlichkeit mit 10 %, sie erhält also den Wert 35.

Diese Werte muss man in einem Array speichern. Dann zieht man eine Zufallszahl zwischen 1 und 100 und schaut in welchen Bereich diese fällt. Ziehe ich also die 29, erhalte ich den Wert 2.


MFG
Lorenz

alzaimar 22. Nov 2007 08:43

Re: Denkanstoß: Brauche gewichtete "Zufallszahlen"
 
Auch ne gute Idee... Verbrät weniger Speicher, ist aber um ein paar ns langsamer.

Reinhardtinho 22. Nov 2007 08:52

Re: Denkanstoß: Brauche gewichtete "Zufallszahlen"
 
Ja,

ich musste diesen Weg einmal gehen, weil ich eine Lotto-Ziehung simuliert habe, da sind es ja ein paar mehr Zahlen und diese dürfen wenn sie einmal gezogen wurden, kein zweites mal gezogen werden. Aber dies ist hier ja anscheinend nicht der Fall.

Progman 22. Nov 2007 08:59

Re: Denkanstoß: Brauche gewichtete "Zufallszahlen"
 
Warum nicht einfach:
Delphi-Quellcode:
  x:=Random(2000);
  if x < 20 then Level:=5 else //0..19, kommt sicher recht selten vor
   if x < 100 then Level:=4 else //20..99, kann schon etwas öfter passieren
    if x < 300 then Level:=3 else //100..299, noch öfter
     if x < 800 then Level:=2 else //300..799, schon relativ großer Bereich
      Level:=1; //800 .. 1999, größter Bereich, hier wirds wohl die meisten Treffer geben
Ist zwar alles etwas willkürlich gewählt, aber es wäre eine Möglichkeit.

guidok 22. Nov 2007 09:08

Re: Denkanstoß: Brauche gewichtete "Zufallszahlen"
 
Danke für die Vorschläge! :-D Sehr kreativ!

Ich überlege mir gerade es mithilfe eines Strings zu machen, in Abwandlung der Methode von alzaimar:

LProb := '111112222333445';

Anschließend kann ich eine Zufallszahl z im Bereich von 1 bis Length(LProb) erzeugen und mit LProb(z) erhalte ich meinen gewünschten Level. Damit habe ich dann ganz einfach die Möglichkeit die Verteilung in einem Editfeld einstellbar zu gestalten.

In der SQL-Abfrage muss ich dann nur WHERE LEVEL=2 abfragen, das wäre sehr angenehm.

Blöd ist allenfalls, dass ich nun bei einer richtigen Antwort durch Addition von 1 direkt einen Level höher springen würde und das geht mir etwas zu fix. Ich hätte da schon ganz gerne eine ähnliche Abstufung wie oben. Also 5 richtige Antworten -> Level 2, weitere richtige Antworten -> Level 3, usw. Dazu muss ggf. noch ein weiteres Feld in die Tabelle nehmen, in dem ich die richtigen Antworten speichern kann, damit die Rechung ausgeführt werden kann.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz