mehrere Zufallszahlen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Bindl
User
Beiträge: 70
Registriert: Donnerstag 27. Oktober 2016, 11:48

Hi zusammen, ich soll folgendes Programm schreiben:
Schreiben Sie ein Programm, welches dem Anwender auf Wunsch 1 bis 4 Reihen, 4 Zufallszahlen ausgibt (zwischen 1-10): (Random randint).
Achten Sie darauf, dass keine Zahl pro Reihe doppelt erscheint.

Nun würde ich zunächste random einbauen, nur dann weiß ich nur wie ich eine Zufallszahl erzeuge.
Muss ich um mehrere Zufallszahlen zu erstellen eine Schleife um random einbauen?
Wie schaffe ich es jedoch das die Zufallszahlen innerhalb einer Zeile nie gleich sind?


Danke schonmal für die Hilfe im voraus
BlackJack

@Bindl: Wenn `randint()` vorgegeben ist, dann musst Du Dir die bisher erzeugten Zahlen für die Zeile merken und entsprechend oft ”Würfeln” bis Du eine Zahl hast die noch nicht vorkam, und die erst dann hinzufügen.

Wenn man nicht auf `randint()` festgelegt wäre, würde man für so etwas `random.sample()` verwenden.
Bindl
User
Beiträge: 70
Registriert: Donnerstag 27. Oktober 2016, 11:48

Hi,
ich habe nun etwas gefunden. Nur sind noch manche Zufallszahlen gleich. Wie verhindere ich das?

Code: Alles auswählen

i = int(input("Zeilenanzahl (1-4): "))

for i in range(1,i+1):

    import random
    a = random.randint(1,10)
    s = random.randint(1,10)
    d = random.randint(1,10)
    f = random.randint(1,10)
    print(a,s,d,f)
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@Bindl: Wo hast Du denn das "gefunden"? Programmieren ist ja nicht wie Ostern, wo man versteckte Eier finden muß. Sondern man überlegt, wie man die Lösung seines Problems in Programmcode übersetzt. Gleiche Zahlen verhindert man entweder mit shuffle oder mit while-Schleifen.
Bindl
User
Beiträge: 70
Registriert: Donnerstag 27. Oktober 2016, 11:48

Hi,

nun habe ich nochmal darüber nachgedacht und habe eine Lösung gefunden.
Der Kommentar mit den 3 Anführungszeichen, sind meine erste Idee. Die jedoch falsch ist

Code: Alles auswählen

i = int(input("Zeilenanzahl (1-4): "))

"""for i in range(1,i+1):

    import random
    a = random.randint(1,10)
    s = random.randint(1,10)
    d = random.randint(1,10)
    f = random.randint(1,10)
    print(a,s,d,f)"""
# Faslch

x = 1
while x <= i:

    import random
    a = random.randint(1,10)
    s = random.randint(1,10)
    d = random.randint(1,10)
    f = random.randint(1,10)

    if a != s != d != f:
        print(a,s,d,f)
        x += 1
    else:
        continue
BlackJack

@Bindl: So eine Zeichenkette ist kein Kommentar. Das Kommentarzeichen in Python ist #, nur das sind wirklich Kommentare und auch nur die sollte man für Kommentare verwenden. Wenn man einen ganzen Block Quelltext aus- oder wieder einkommentieren möchte, sollte man schauen wie man das bei dem Editor oder der IDE die man verwendet durch Markieren + Tastenkürzel machen kann. Denn jeder vernünftige Editor bietet so eine Funktion.

Importe gehören an den Anfang des Moduls, damit man gleich sehen kann von was ein Modul alles abhängt. Zudem hast Du das in einer Schleife stehen, das heisst es wird in jedem Schleifendurchlauf ausgeführt, führt aber immer zum gleichen Ergebnis. Damit gehört das nicht *in* die Schleife.

Der ``else``-Zweig mit dem ``continue`` ist sinnfrei, der hat keinen Effekt. Wech damit.

Unschön ist hier auch das alles vermischt ist. Eine ”natürliche” Aufteilung wäre es die Erzeugung und Ausgabe von vier Zufallszahlen zu implementieren, und das dann wenn es funktioniert in eine ``for``-Schleife zu stecken die x mal ausgeführt wird. Erzeugung und Ausgabe würde man auch trennen, weil man das getrennt entwickeln und testen kann.

Wenn in der Aufgabe steht 1 bis 4 mal, dann vermute ich mal stark das man das in der Lösung auch *sicherstellen* soll, also das die Eingabe vom Benutzer darauf auch überprüft wird und das er entweder solange gefragt wird bis er was passendes eingibt, oder dass das Programm eine entsprechende Meldung ausgibt und die Zufallszahlen nicht erzeugt/ausgibt wenn der Benutzer etwas falsches eingibt.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@Bindl: die if-Abfrage ist falsch, was Du auch leicht selbst sehen kannst, wenn Du das Programm mal laufen läßt.

Code: Alles auswählen

>>> 1 != 2 != 1 != 2
True
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,


ich nehme mal an, dass die Hausaufgabe schon abgefragt wurde.
Ab und zu probiere ich mich auch darin. Einfach zur Übung.

Ich habe das Gefühl, dass meine Lösung einfach too much ist.
Vermutlich nutze ich sogar das memorizing falsch.

Code: Alles auswählen

from random import randint as rm

def zahlen(fkt):
    memorize = []
    def helper(x):
        while len(memorize) < x:
            zahlen_reihe = fkt()
            gefunden = check_double(zahlen_reihe, memorize)
            if not gefunden:
                memorize.append(zahlen_reihe)
        
        return memorize
    return helper

def check_double(zahlen_reihe, memorize):    
    for reihe in memorize:
        for zahl in reihe: 
            if zahl in zahlen_reihe:
                return True
    return False

def random():
    zahlen = set()
    while len(zahlen) < 4:
        zahl = rm(1,100)
        zahlen.add(zahl)
    return zahlen



if __name__ == '__main__':
    random = zahlen(random)
    for reihe in random(20):
        print reihe
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@sebastian0202: ich weiß nicht, wie man randint mit rm abkürzen kann, da ja gar kein m vorkommt. Generell gilt, lieber nichts abzukürzen, weil man aus rm wirklich nicht mehr ableiten kann, was die Funktion machen könnte. Dekoratoren wendet man durch @zahlen auf eine Funktion an, und nicht irgendwo im Hauptprogramm durch Aufruf des Dekorators. zahlen sagt einem auch nicht, was denn der Dekorator tut.

memorize ist eine globale Variable, und auch nocht dort, wo man absolut keine globale Variable erwarten würde. Was liefert denn der zweite Aufruf von random? Oder gar ein Aufruf von random(10) nach random(20)?

Deine Funktion random ist auch sehr speziell. Genau 4 Zahlen aus dem Zahlenraum bis 100.

Wie BlackJack schon geschrieben hat, würde man so eine Aufgabe mit random.sample lösen, dann kommt auch gleich eine Fehlermeldung, falls man zu viele Zahlen will.

Code: Alles auswählen

from itertools import islice
import random

def get_groups_of_random_numbers(a, b, groups, numbers_per_group):
    numbers = iter(random.sample(range(a, b+1), groups * numbers_per_group))
    return [list(islice(numbers, numbers_per_group)) for _ in range(groups)]

print get_groups_of_random_numbers(0, 100, groups=20, numbers_per_group=4)
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

sebastian0202 hat geschrieben:Ich habe das Gefühl, dass meine Lösung einfach too much ist.
Mir ist nicht klar, warum du die Funktionen zahlen und get_double erstellt hast. Die Aufgabe lässt sich doch problemlos alleine mit deiner Funktion random lösen.

Apropos random: Die Namensvergabe ist richtig übel. Warum nennt man eine Funktion genau so wie ein Modul der Standardbibliothek? Um warum bindest du anschließend an diesen Namen auch noch den Rückgabewert derselben Funktion? Warum wird randint als nichtssagendes rm importiert? zahlen ist kein sinnvoller Name für eine Funktion. Eine Funktion tut etwas, also wäre zahlen_ermitteln schon mal besser (aber auch noch nicht ganz schön).
Zuletzt geändert von /me am Donnerstag 24. November 2016, 11:06, insgesamt 1-mal geändert.
BlackJack

@sebastian0202: Ich finde sehr verwirrend das `zahlen` und `random` als Namen mehrfach/für verschiedene Dinge verwendet werden. Und `zahlen` ist auch ein schlechter Name für eine Funktion. Der sagt mir so überhaupt nicht das es eine Funktion ist und auch nicht was sie macht.

Ausserdem ist das wohl auch keine Lösung der Aufgabe wenn ich das richtig sehe. Eine Zahl darf laut Aufgabe *pro Reihe* nur einmal vorkommen. Ich glaube Du schränkst das hier deutlich weiter ein, und zwar so das 4 Reihen mit je vier Zufallszahlen zwischen 1 und 10 gar nicht mehr möglich wäre. Das sind aber die Vorgaben der Aufgabe.
Benutzeravatar
noisefloor
User
Beiträge: 4253
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wenn `randint()`Pflicht ist, würde ich das mit einem Set machen:

Code: Alles auswählen

>>> import random
>>> for i in range(0, 4):
        result = set()
	    while len(result) < 4:
		    result.add(random.randint(1, 10))
        print(result)
Müsste man halt nur noch von immer 4 Reihen Zufallszahlen auf 1 - 4 Reihen anpassen.

Gruß, noisefloor
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,



r ando m, daher rm.
Die Abkürzung ist doof. Mach ich eigentlich nicht.
Random/Zahlen als Funktionsname und Variable ist sehr dämlich.
Habe das eben auf die Schnelle gepinselt. Ist ja gruselig zu lesen. :mrgreen:

Dann ist es also normal, dass Funktionen aus 4 oder mehr Wörter bestehen?

Ich hab die Aufgabe für mich erweitert. Keine doppelten Zahlen in irgendeiner einer der generierten Gruppen.
Ich wollte das memorizing anwenden um das zu lösen.
Aber irgendwie ist das bei dieser Aufgabe too much.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@sebastian0202: ein Memorizing ist nur dann sinnvoll, wenn die selben Inputdaten zu den selben Ergebnissen führen und die Berechnung sehr lange dauert. Punkt 1 ist bei Zufallszahlen explizit nicht erwünscht, bei Punkt 2 dauert die Berechnung auch beim besten Willen nicht lang.

Für dieses Problem braucht man einen Unique-Filter, der aber nicht als Dekorator ausgeführt werden kann, sondern eben als Filter.
BlackJack

@sebastian0202: Mich hat dieses `memorize` total durcheinander gebracht. Mal davon abgesehen das dieser Namen eher für eine Funktion passt, sollte das eigentlich `result` heissen, denn das ist es ja letztendlich. Und ich finde die Aufteilung auf die Funktionen auch total komisch und nicht wirklich nachvollziehbar. Das verwirrt mehr als das es nachvollziehbar macht, was dieses Programm eigentlich macht.

Vier oder mehr Wörter in einem Funktionsnamen würde ich nicht für normal halten. Bei mehr als drei sollte man mal über einen besseren Namen nachdenken.
BlackJack

Unübersichtlich ist okay wenn es ”vintage” ist. C64-Basic-Lösung:
[codebox=locobasic file=Unbenannt.txt] 10 X=RND(-TI):M=4:DIM N(M)
20 PRINT"HOW MANY REPETITIONS (1 -";M;"{LEFT})";
30 INPUT R:IF R<1 OR R>M THEN 20
40 FOR I=1 TO R:C=1:FOR J=1 TO M:N(J)=0:NEXT
50 F=0:X=INT(RND(1)*10)+1:FOR J=1 TO C:IF N(J)=X THEN F=1:J=C
60 NEXT:IF F THEN 50
70 N(C)=X:C=C+1:IF C<=M THEN 50
80 FOR J=1 TO M:PRINT N(J);:NEXT:PRINT:NEXT[/code]
BlackJack

”Komplettlösung” mit Abfrage der Wiederholungen und Überprüfung ob der Wert im Bereich 1 bis 4 liegt.

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function

from random import randint


lower_limit, upper_limit = 1, 4
while True:
    repeat_count = int(
        input('Zeilenanzahl ({}-{}): '.format(lower_limit, upper_limit))
    )
    if lower_limit <= repeat_count <= upper_limit:
        break
    else:
        print(
            'Bitte nur Zahlen zwischen {} und {} eingeben.'.format(
                lower_limit, upper_limit
            )
        )

for _ in range(repeat_count):
    numbers = list()
    while len(numbers) < 4:
        number = randint(1, 10)
        if number not in numbers:
            numbers.append(number)

    numbers.sort()
    print(' '.join(map(str, numbers)))
Antworten