Knifflige Aufgabe zur Statistik

Hallo,
ich habe die Ziffern 1, 1, 2, 2, 2, 3, 3, 4. Es sind acht Stück und es sollen 6-stellige Zahlen gebildet werden.
Wenn es 8-stellig sein sollte, wäre es kein Problem, sie mit einer Formel aus der Kombinatorik abzuzählen.
Wenn es sechs verschiedene Ziffern wären, dann auch nicht.
Das Problem ist ja hier, dass ich nicht weiß, welche Ziffern jeweils noch übrig sind.

Weiß jemand eine Formel dafür, oder bräuchte man ein Abzählprogramm für den Computer, dass so funktioniert, dass man sich erstmal sechs Ziffern herausnimmt, die Möglichkeiten abzählt, dann eine Ziffer durch eine der fehlenden Zahl austauschen, usw. bis man alle Ziffern in jeder Kombination mal hatte.
Die Möglichkeiten addiert man dann zusammen, nachdem man eine Zahl durch eine der anderen übrig gebliebenen Ziffern ersetzt.

Danke
Tim

Hallo,

Weiß jemand eine Formel dafür, oder bräuchte man ein
Abzählprogramm für den Computer, dass so funktioniert, dass
man sich erstmal sechs Ziffern herausnimmt, die Möglichkeiten
abzählt, dann eine Ziffer durch eine der fehlenden Zahl
austauschen, usw. bis man alle Ziffern in jeder Kombination
mal hatte.

Ich habe das mal spasseshalber programmiert, nur in der leichten Variation dass erst mal alle Permutationen gebildet werden, dann die ersten beiden Elemente entfernt werden und dann die verschiedenen Vorkommen gezählt werden:

#!/usr/bin/perl
use strict;
use warnings;
use Algorithm::Combinatorics qw(permutations);

my %seen;
my $i = permutations([1, 1, 2, 2, 2, 3, 3, 4]);
while (my $p = $i-\>next){
 splice @$p, 0, 2;
 my $number = join '', @$p;
 $seen{$number}++;
}

print scalar(keys %seen), " solutions\n";

Ergebnis: 990 Zahlen.

Das geht sicher viel effizienter, aber dazu hab ich gerade keine Lust :wink:

Grüße,
Moritz

Ich habe das mal spasseshalber programmiert, nur in der
leichten Variation dass erst mal alle Permutationen gebildet
werden, dann die ersten beiden Elemente entfernt werden und
dann die verschiedenen Vorkommen gezählt werden:

Und wie stellst du sicher, dass die Ziffern, die du abschneidest, auch dann beim nächsten mal in die Permutation eingehen, weil einfach weglassen gilt ja nicht :smile:.

#!/usr/bin/perl
use strict;
use warnings;
use Algorithm::Combinatorics qw(permutations);

my %seen;

Wofür steht das Zeichen „%“?

my $i = permutations([1, 1, 2, 2, 2, 3, 3, 4]);

Hier bildest du ja die Permutation aus allen Zahlen, nämlich (2 aus 8)*(3 aus 6)*(2 aus 3)*(1 aus 1), stimmst?

while (my $p = $i->next){

Hier wird aus dem Array i in der Schleife immer das nächste genommen bis es leer ist

splice @$p, 0, 2;

Hier schneidest du doch zwei Ziffern von jeder möglichen 8-ziffrigen Zahl ab

my $number = join ‚‘, @$p;
$seen{$number}++;

Was in diesen Zeilen geschieht, weiß ich leider nicht

}

print scalar(keys %seen), " solutions\n";

Hier ist einfach Ergebnisausgabe

Wenn du vielleicht noch kurz das Programm kurz erläutern könntest, wäre sehr nett und informativ.
Danke

Hallo,

Ich habe das mal spasseshalber programmiert, nur in der
leichten Variation dass erst mal alle Permutationen gebildet
werden, dann die ersten beiden Elemente entfernt werden und
dann die verschiedenen Vorkommen gezählt werden:

Und wie stellst du sicher, dass die Ziffern, die du
abschneidest, auch dann beim nächsten mal in die Permutation
eingehen, weil einfach weglassen gilt ja nicht :smile:.

Ich verstehe deine Frage nicht so ganz.

Ich bilde aller Zahlen aus 8 Buchstaben, und schneide die ersten beiden weg, und Ziffern ab. Und dann zähle ich, wie viele unterschiedliche Zahlen dadurch entstehen.

Das ist gleichbedeutend mit „auf alle möglichen Arten 6 der 8 Ziffern wählen und alle möglichen Kombinationen bilden“.

> > #!/usr/bin/perl  
> > use strict;  
> > use warnings;  
> > use Algorithm::Combinatorics qw(permutations);  
> >   
> > my %seen;
> 
> Wofür steht das Zeichen "%"?


Für ein Assoziatives Array, in Perl auch "Hash" genannt.



> > my $i = permutations([1, 1, 2, 2, 2, 3, 3, 4]);
> 
> Hier bildest du ja die Permutation aus allen Zahlen, nämlich  
> (2 aus 8)\*(3 aus 6)\*(2 aus 3)\*(1 aus 1), stimmst?


nicht ganz. $i ist ein Iterator, der bei jedem Aufruf von $i-\>next die nächste Permutation als Referenz auf ein Array liefert.



> > while (my $p = $i-\>next){
> 
> Hier wird aus dem Array i in der Schleife immer das nächste  
> genommen bis es leer ist  
> 
> > splice @$p, 0, 2;
> 
> Hier schneidest du doch zwei Ziffern von jeder möglichen  
> 8-ziffrigen Zahl ab


richtig.



> > my $number = join '', @$p;  
> > $seen{$number}++;
> 
> Was in diesen Zeilen geschieht, weiß ich leider nicht


Bisher liegt die Zahl in @$p als Liste von Ziffern vor. Hier wird eine Zahl daraus gebaut (mit join), und im Hash %seen der Wert, der zur Zahl $number gehört, um eins erhöht.



> > }  
> >   
> > print scalar(keys %seen), " solutions\n";

Hier ist einfach Ergebnisausgabe

Richtig.

Grüße,
Moritz

Hallo Tim,

die Anzahl der 6-stelligen Zahlen, die man bilden kann, ist gleich der Anzahl der Möglichkeiten die 8 Zahlen anzuordnen (Permutation mit Wiederholung) multipliziert mit der Anzahl der Möglichkeiten zwei der 8 Zahlen zu streichen (Kombination).

Viele Grüße,
Falk

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Ich verstehe deine Frage nicht so ganz.

Klärt sich sicher im Verlauf diese Beitrags.

my $number = join ‚‘, @$p;
$seen{$number}++;

Was in diesen Zeilen geschieht, weiß ich leider nicht

Bisher liegt die Zahl in @$p als Liste von Ziffern vor. Hier
wird eine Zahl daraus gebaut (mit join), und im Hash %seen der
Wert, der zur Zahl $number gehört, um eins erhöht.

Aber wenn du doch von allen möglichen Zahlen, die sich aus der Permutation aller acht Ziffern ergeben, das sind 1680 verschiedene Zahlen, die ersten beiden immer abschneidest, dann kann man den Zähler doch erst inkrementieren, wenn sichergestellt ist, dass man die 6-stellige Zahl nicht schon hatte. Wo prüft das Programm das? Sonst zählst du ja irgendwo was doppelt. Du kommst ja auch auf weniger, nämlich 990 verschiedene 6-stellige Zahlen. Also irgendwo ist darauf ja geprüft worden, dass keine gleichen 6-stelligen Zahlen gezählt werden. Aber wo im Programm?

Wenn du mir das vielleicht noch kurz zeigen könntest
Danke

Hallo Tim,

die Anzahl der 6-stelligen Zahlen, die man bilden kann, ist
gleich der Anzahl der Möglichkeiten die 8 Zahlen anzuordnen
(Permutation mit Wiederholung) multipliziert mit der Anzahl
der Möglichkeiten zwei der 8 Zahlen zu streichen
(Kombination).

Ich denke nicht, dass das richtig ist.
Das würde mir ja mehr mögliche 6-stellige Zahlen erlauben.
Aber wenn eine Zahl weniger Stellen hat, dann gibt es auch nicht so viele Möglichkeiten wie bei einer Zahl, die mehr Stellen hat.

Oder wer weiß da was anderes?

Hallo,

Aber wenn du doch von allen möglichen Zahlen, die sich aus der
Permutation aller acht Ziffern ergeben, das sind 1680
verschiedene Zahlen, die ersten beiden immer abschneidest,
dann kann man den Zähler doch erst inkrementieren, wenn
sichergestellt ist, dass man die 6-stellige Zahl nicht schon
hatte.

Du solltest dich nicht so aufs Inkrementieren des Zählers versteifen, ich hätte auch genauso gut $seen{$number} = 1; schreiben können. Ich zähle am Ende nur, wie viele Einträge es in dem Hash gibt, der Wert des Zählers wird bisher ignoriert.

Wenn ein Eintrag bisher schon existiert wird nur der Zähler erhöht, wenn er nicht existiert wird er neu angelegt - diese Überprüfung macht Perl implizit (und wird „Autovification“ genannt).

Grüße,
Moritz