staging.inyokaproject.org

[bash] Zufallszahlen nach Häufigkeit auswerten

Status: Ungelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

SleazeRocker

Anmeldungsdatum:
10. August 2018

Beiträge: 6

Moin!

Ich bin Linux-Neuling und bräuchte mal Hilfe bei einer Aufgabe aus dem Lehrbuch:

Aufgabe: Es sollen 1000 Zufallszahlen (Bereich 0 - 9) generiert und die Häufigkeit ausgewertet werden.

Erlaubte Befehle: for, sort, uniq, awk, echo

Erwartete Ausgabe:

Die Zahl 0 ist 96 mal aufgetreten.
Die Zahl 1 ist 113 mal aufgetreten.
Die Zahl 2 ist 110 mal aufgetreten.
Die Zahl 3 ist 103 mal aufgetreten.
Die Zahl 4 ist 88 mal aufgetreten.
Die Zahl 5 ist 83 mal aufgetreten.
Die Zahl 6 ist 93 mal aufgetreten.
Die Zahl 7 ist 105 mal aufgetreten.
Die Zahl 8 ist 102 mal aufgetreten.
Die Zahl 9 ist 107 mal aufgetreten.

Ich finde da überhaupt keinen Ansatz und wäre für eine Lösung dankbar.

Bearbeitet von rklm:

Codeblock. Bitte beachte Forum/Syntax und nutze die Vorschau-Funktion!

unbuntuS12

Anmeldungsdatum:
2. Juni 2010

Beiträge: 1816

Moin!

als ersters der Hinweis auf die manpages der entsprechenden Programme:

man for
man sort
man uniq
man awk
man echo

Du verschaffst dir also einen Überblick darüber, was deine Werkzeuge überhaupt können. Ggf. suchst du auch einmal im Internet zu jedem Programm, einfach um dir Beispiele von anderen anzugucken.

Dann vergegenwärtigst du dir, was du machen sollst: Du sollst Zufallszahlen erstellen. Welches dieser Programme könnte das tun? Nun nehmen wir an, du hast eine Liste von 1000 Zufallszahlen. Wie gehst du weiter vor? Na ja, sortieren klingt gut, und dann zählt man die Gruppen und dann bist du schon fast am Ziel. Hilft dir der Ansatz?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

Beim ersten ”Programm” wird man nicht funktionieren, weil's kein Programm ist, sondern ein Schlüsselwort in der Bash. Da man durch help ersetzen. ☺

echo ist zwar (auch) ein Programm, aber die Shell hat das auch als Befehl eingebaut, also ist auch hier help sinnvoller als man.

unbuntuS12

Anmeldungsdatum:
2. Juni 2010

Beiträge: 1816

Marc_BlackJack_Rintsch schrieb:

Beim ersten ”Programm” wird man nicht funktionieren, weil's kein Programm ist, sondern ein Schlüsselwort in der Bash. Da man durch help ersetzen. ☺

Das hatte ich auch vermutet und deshalb vorher probiert. Und die erste Zeile der Manpage lautet bei mir:

DESCRIPTION
       For is a looping command, similar in structure to the C for statement

Allerdings kommt die Manpage auf meinem System, wie ich danach erst gesehen habe, von der Sprache TCL - um die es ja hier nicht geht. Insofern hast du Recht.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

Die Liste der erlaubten Befehle ist ziemlich üppig. Ich habe da nur for und echo von gebraucht, also die beiden Sachen die in der Bash schon eingebaut sind, und damit kein externes Programm:

1
2
3
4
5
6
7
8
9
#!/bin/bash

unset counts
for (( i = 0; i < 1000; i++ )); do
    ((counts[RANDOM % 10]++))
done
for (( i = 0; i < 10; i++ )); do
    echo "Die Zahl $i ist ${counts[i]} mal aufgetreten."
done

SleazeRocker

(Themenstarter)

Anmeldungsdatum:
10. August 2018

Beiträge: 6

Schonmal danke für die Antworten.

Irgendwie sehe ich da kein Land und weiß nicht wie ich da anfangen soll. Für Zufallszahlen kenne ich bis jetzt auch nur $RANDOM.

Leider liegen die Aufgaben nur als PDF vor und der Lösungsteil fehlt. ☹

EDIT:

@Marc

WOW, danke!!! Das hilft mir sehr weiter. Ich wusste zb. gar nicht, wie ich das in die Schleife hätten packen sollen. Die sind noch meine große Schwäche.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@SleazeRocker: Gehen die Aufgaben denn von der Bash aus? POSIX kennt diese Art der for-Schleife zum Beispiel nicht. Und seq ist nicht in der Liste der erlaubten Befehle. Wie hat den das Lehrbuch for-Schleifen bis zu dem Zeitpunkt verwendet?

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7795

Wahrscheinlich ist die Lösung von Marc so ziemlich das Gegenteil von dem, was dir das Lehrbuch vermitteln wollte... wie man verschiedene Befehle miteinander verknüpft und Ausgaben verarbeitet. 😉

Das Lehrbuch wird dir die Bash als Werkzeug zum nacheinander-ausführen von Befehlen verkaufen wollen, während Marc's Ansatz eher der einer vollwertigen Programmiersprache ist.

Die Aufgabe so wie gewünscht mit sort, uniq usw. zu lösen ist nicht verkehrt.

SleazeRocker

(Themenstarter)

Anmeldungsdatum:
10. August 2018

Beiträge: 6

Marc_BlackJack_Rintsch schrieb:

@SleazeRocker: Gehen die Aufgaben denn von der Bash aus? POSIX kennt diese Art der for-Schleife zum Beispiel nicht. Und seq ist nicht in der Liste der erlaubten Befehle. Wie hat den das Lehrbuch for-Schleifen bis zu dem Zeitpunkt verwendet?

Ich habe deinen Code eben getestet und es klappt wie gewünscht.

Die PDFs habe ich vom Praktikumsbetrieb bekommen, ist auch nur der Aufgabenteil aus dem Buch. Bin derzeit krank geschrieben und wollte zuhause mal die Aufgaben abarbeiten. Meine "Lehrbücher" waren bis jetzt "Google" und "Ubuntuuser". 😀 Wie gesagt, bin kompletter Neuling in Sachen skripting und Linux.

Besonders die Schleifen sind mein Problem... verstehe die Syntax noch nicht so richtig.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@frostschutz: Ich teile Deine Vermutung, aber dann hätten sie im Lehrbuch IMHO besser „verwenden sie ausschliesslich und alle folgenden Befehle sinnvoll in Ihrer Lösung“ geschrieben, statt „erlaubte Befehle: …“. ☺

Ich hätte jedenfalls ohne weitere Anmerkungen zur Aufgabe und unter der Voraussetzung, dass wir von der Bash reden, meine Lösung abgegeben und es als Vorteil angesehen, dass keine externen Programme verwendet wurden und es eine einfache und ziemlich naheliegende Lösung ist.

Falls es nicht die Bash sondern eine POSIX-Kompatible sein sollte, hätte ich kurzerhand das ganze komplett in AWK verlegt um nicht so viele verschiedene externe Werkzeuge verwenden zu müssen. In AWK sieht das der Bash-Lösung auch sehr ähnlich:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/usr/bin/awk -f

BEGIN {
    srand()
    for (i = 0; i < 1000; i++) {
        counts[int(rand() * 10)]++
    }
    for (i = 0; i < 10; i++) {
        printf "Die Zahl %d ist %d mal aufgetreten.\n", i, counts[i]
    }
}

Wenn man die Aufgabe als „benutzen sie alle folgenden Befehle“ sieht, dann ist AWK ja nur dazu da, um die Ausgabe des vorherigen Schritts in einer anderen Reihenfolge und in eine Zeichenkette eingebettet auszugeben, weil in der Befehlsliste kein while und kein read vorkommt.

@SleazeRocker: Diese Art eine for-Schleife mit einer Laufvariablen, beziehungsweise mit den drei Teilen Initialisierung, Abbruchtest, Aktualisieren zu schreiben ist bei vielen Programmiersprachen in dieser Form üblich. In AWK wie man in diesem Beitrag sieht auch.

SleazeRocker

(Themenstarter)

Anmeldungsdatum:
10. August 2018

Beiträge: 6

@Marc

Danke für die Erklärungen. Wird wohl noch ein hartes Stück Arbeit... ich war auch von der Befehlsliste erschlagen und hab versucht die komplett unterzubringen.

Mache gerade eine Umschulung zum FiSi und mache Praktikum in einem Rechenzentrum wo Linux das A und O ist.

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7795

Marc_BlackJack_Rintsch schrieb:

@frostschutz: Ich teile Deine Vermutung, aber dann hätten sie im Lehrbuch IMHO besser „verwenden sie ausschliesslich und alle folgenden Befehle sinnvoll in Ihrer Lösung“ geschrieben, statt „erlaubte Befehle: …“. ☺

"Erlaubte Befehle" impliziert das ziemlich stark.

dann ist AWK ja nur dazu da, um die Ausgabe des vorherigen Schritts in einer anderen Reihenfolge und in eine Zeichenkette eingebettet auszugeben

Ja, genau so...

1. for-Schleife die 1000 Zufallszahlen ausgibt.

2. sort was diese Zufallszahlen fein säuberlich aufreiht.

3. uniq was die aufgereihten Zufallszahlen zählt (uniq zählt nur sich unmittelbar wiederholende Zeilen, daher zuerst sort)

4. awk was diese Zahlen in den gewünschten Aussage-Satz bringt.

Das ganze ist dann ein "einfacher" Einzeiler:

for …; do echo …irgendwas mit $RANDOM…; done | sort … | uniq … | awk '{ print … }'

Und sehr wahrscheinlich steht es haargenau so in der erwarteten Standardlösung drin, da gibt es nicht mehr allzuviel Möglichkeiten zum Abweichen.

Und auf die Lösung kommst du eben schrittweise durch |… weglassen:

for …; do echo …; done

# ausgabe: 1000 zufallszahlen

for …; do echo …; done | sort …

# ausgabe: 1000 zufallszahlen sortiert

for …; do echo …; done | sort … | uniq …

# ausgabe: 10 zeilen der form <anzahl> <zufallszahl>

for …; do echo …; done | sort … | uniq … | awk '{ print …; }'

# ausgabe: Zahl X kam Y mal vor.

Schrittweise weil wenn du nicht weisst, was die vorhergehenden Befehle ausgeben, dann kannst du auch nicht wissen, wie du das nach der Pipe | weiterverarbeiten sollst.

Die … darf der TE selber ausfüllen. ☺

SleazeRocker

(Themenstarter)

Anmeldungsdatum:
10. August 2018

Beiträge: 6

Sehr cool, danke. ☺ Das hilft mir echt weiter, besonders die Reihenfolge.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Allerdings kommt die Manpage auf meinem System, wie ich danach erst gesehen habe, von der Sprache TCL - um die es ja hier nicht geht. Insofern hast du Recht.

Hier nicht, weil es keine Manpage zu bashs for gibt, aber ansonsten liefert man den ersten Treffer, den es findet. Bei Mehrdeutigkeiten kann man mit

1
man -a MEHRDEUTIG

alle manpages zu einem Stichwort auflisten lassen. Mit q beendet man die erste, womöglich nicht gesuchte Fundstelle, und wird dann gefragt, ob man die nächste Fundstelle lesen will.

Beispiele:

1
2
man -a regex
man -a crontab
Antworten |