Leser: 28
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
#!/usr/bin/perl use strict; use warnings; my $val=45; my @peg=(1..45); #Karten mischen for(@peg) { my $p=int(rand(scalar @peg)); my $k=$_; $_=$peg[$p]; $peg[$p]=$k; } # erste Hand abheben my @hand=splice(@peg,0,4); # sicherheitshalber einen Counter # damit das Script nach 1000 Durchläufen terminiert my $cnt=0; while(@hand && $cnt++<1000) { # Alle Kombinationen in der Hand Testen my @result=test_values($val,@hand); # etwas gefunden? if(@result) { # Sortieren und doppelte Einträge entfernen my %found=(); @result=sort{@$b <=> @$a}map{$found{join(',', sort @$_)}++?():$_}@result; for my $card (@{$result[0]}) { # Karte ablegen @hand=map{$card==$_?():$_}@hand; # und in den Stapel push(@peg,$card); } print "Eine Kombination gefunden!(".join('+',sort(@{$result[0]})).")\n"; } else { # eine Karte aus dem Stapel ziehen # habe ich gemacht, damit das Programm auch mal ein Ende findet. push(@hand,shift(@peg)); print "Keine Kombination gefunden!\n"; } print "Die Hand ist: ".join(', ',sort @hand)."\n\n"; print "Nächste Runde!\n\n"; } if(@hand) { print "Verloren!\n"; } else { print "Gewonnen! ($cnt Rounds)\n"; } ######################################################################## sub test_values { # der gesuchte wert my $val=shift; # die Karten my @cards=@_; # wenn alle Karten größer als der Suchwert, # dann Abbruch. return () unless(grep{$_<=$val}@cards); # wenn nur noch eine Karte # und diese nicht gleich dem gesuchten Wert, # dann Abbruch! return () if(@cards==1 && $cards[0] != $val); # summe aller Karten my $sum=0; map{$sum+=$_}@cards; # wenn die summe kleiner als der Suchwert abbrechen! return () if($sum<$val); # wenn die Summe der Suchwert ist, # dann diese Liste zurück return \@cards if($sum==$val); my @ret=(); # wenn eine Karte dem Suchwert entspricht if(grep{$val==$_}@cards) { push(@ret,[$val]); push(@ret,test_values($val,map{$_==$val?():$_}@cards)); } else { # alle Karten durch gehen for my $card (@cards) { # mit einer Karte weniger # und kleinerem Suchwert in die nächste Rekursion my @r=test_values($val-$card,map{$_==$card?():$_}@cards); if(@r) { push(@$_,$card) for(@r); push(@ret,@r); } } } return @ret; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @peg=((1..12)x4,13..19);# qw /1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 10 10 10 10 11 11 11 11 12 12 12 12 13 14 15 16 17 18 19/; my @range=(1..26); #Karten mischen for(@peg) { my $p=int(rand(scalar @peg)); my $k=$_; $_=$peg[$p]; $peg[$p]=$k; } # Erste Hand abheben my @hand=splice(@peg,0,4); my $cnt=0; while(@hand && $cnt++<1000) { print "Hand ist nun: ".join(', ',sort @hand)."\n"; my %result; my %found; for (combinations(@hand)) { next if($found{"@$_"}++); push(@{$result{sum(@$_)}},$_); } # found if(%result) { my ($val,@best)=best_choice(\@range,\%result); # remove card from hand for my $card (@best) { # remove card from hand @hand=map{$card==$_?():$_}@hand; # put the Cards back push(@peg,$card); } print "Kombination gefunden!(".join(' + ',@best)." = $val)\n"; } else { print "Keine Kombination gefunden!\n"; # Spiel abbrechen, verloren... last; } # hand füllen push(@hand,shift(@peg)) while(@hand && @hand<4); print "\n"; } if(@hand) { print "VERLOREN!\n"; } else { print "GEWONNEN! ($cnt RUNDEN)\n"; } ######################################################################## sub combinations { my @cards=@_; return [] unless (@cards); return \@cards if(@cards==1); my @ret; my %found; for my $cpos (0..$#cards) { my $card=$cards[$cpos]; my @list=@cards; splice(@list,$cpos,1); push(@ret,[$card]); for my $r (combinations(@list)) { my @rr=sort(@$r,$card); # übergehe schon gefundene Kombinationen... next if($found{"@rr"}++); push(@ret,\@rr); } } return @ret; } sub best_choice { my $vals=shift; my $found=shift; my @best; my $val; for my $v (@$vals) { next unless($found->{$v}); for my $cards (@{$found->{$v}}) { # wenn noch nichts gesetzt, # dann nimm das Erstbeste unless(@best && $val) { @best=@$cards; $val=$v; } # die Längst Zahlenreihe, # oder wenn gleich lang, # die größte Summe if(@best<@$cards || (@best==@$cards && $val<$v) ) { @best=@$cards; $val=$v; } } } #es wurde nichts gefunden ... return 0 unless($val && @best); # das Ergebnis return ($val,@best); } sub sum { my $summ=0; $summ+=$_ for(@_); return $summ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
my @chancen=();
push(@chancen, $hand[0]);
push(@chancen, $hand[1]);
push(@chancen, $hand[0]+$hand[1]);
push(@chancen, $hand[2]);
push(@chancen, $hand[0]$hand[2]);
push(@chancen, $hand[1]+$hand[2]);
push(@chancen, $hand[0]+$hand[1]+$hand[2]);
push(@chancen, $hand[3]);
push(@chancen, $hand[0]+$hand[3]);
push(@chancen, $hand[1]+$hand[3]);
push(@chancen, $hand[0]+$hand[1]+$hand[3]);
push(@chancen, $hand[2]+$hand[3]);
push(@chancen, $hand[0]+$hand[2]+$hand[3]);
push(@chancen, $hand[1]+$hand[2]+$hand[3]);
push(@chancen, $hand[0]+$hand[1]+$hand[2]+$hand[3]);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
sub combinations { # übernehme die Karten my @cards=@_; # wenn keine Karten an die Funktion übergeben wurden liefere eine leere Liste zurück return [] unless (@cards); wenn nur eine Karte in der Liste ist dann liefere nur die Liste zurück return \@cards if(@cards==1); # erzeuge die liste mit den restlichen Kombinationen: my @ret; # solange noch karten vorhanden sind: while(@cards) { # nimm die erste Karte heraus my $card=shift(@cards); # füge diese Karte des RückgabeArrays hinzu push(@ret,[$card]); # rufe die Funktion selber wider auf und gehe das Ergebnis durch (ist ein array) # das ist rekursive teil, das die Funktion sich immer wieder selber aufruft, # die übergebene liste ist aber immer um ein Element kürzer # darum kommt die Rekursion irgendwann zu einem Ende (siehe oben) for my $r (combinations(@cards)) { # $r enthält eine Arrayrefenz! # füge die herausgenommene Karte wieder ein # und füge die das dem RückgabeArray hinzu push(@ret,[@$r,$card]) if(@$r); } } # gib das RückgabeArray zurück return @ret; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
aufruf: combinations(1 2 3 4)
bekomme: 1 2 3 4
gehe liste durch
noch 1 2 3 4 in der Liste
@zurück1 += [ 1 ]
aufruf combinations(2 3 4)
bekomme: 2 3 4
gehe liste durch
noch 2 3 4 in der Liste
@zurück2 += [ 2 ]
aufruf combinations(3 4)
bekomme: 3 4
gehe liste durch
noch 3 4 in der liste
@zurück3 += [ 3 ]
aufruf combinations(4)
bekomme: 4
gebe ( [ 4 ] ) zurück
@zurück3 += [ 3 4 ]
noch 4 in der liste
@zurück3 += [ 4 ]
aufruf combinations()
bekomme:
gebe ( [ ] ) zurück
gebe zurück ( [ 3 4 ] [ 4 ] )
@zurück2 += [ 2 3 4 ]
@zurück2 += [ 2 4 ]
noch 3 4 in der liste
@zurück2 += [ 3 ]
aufruf combinations(4)
bekomme: 4
gebe ( [ 4 ] ) zurück
@zurück2 += [ 3 4 ]
noch 4 in der liste
@zurück2 += [ 4 ]
aufruf combinations()
bekomme:
gebe ( [] ) zurück
gebe zurück ([ 2 ] [ 2 3 4 ] [ 2 4 ] [ 3 4 ] [ 4 ])
@zurück1 += [ 1 2 ]
@zurück1 += [ 1 2 3 4]
@zurück1 += [ 1 2 4 ]
@zurück1 += [ 1 3 4 ]
@zurück1 += [ 1 4 ]
noch 2 3 4 in der liste
@zurück1 += [ 2 ]
aufruf combinations( 3 4 )
bekomme: 3 4
...
1 2 3 4 5 6 7 8 9 10 11
sub combinations { return [] unless (@_); my @ret; while(@_) { my $card=shift(@_); push(@ret,[@$_,$card]) for(combinations(@_)) } return @ret; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
# gegeben sei ein Array mit Arrays: my @array=( [1], [1 3 4], [1 2 3 4], [1 2 3 4], [2 3 1 4], [4 3 1], ); # definiere einen Hash, # der die als Indikator für die doppelten Werte dienen soll: my %unique; # das Array für die Werte # ohne die doppelten my @unique_array; # gehe das Array @array durch: for my $array_ref (@array) { # $array_ref ist eine referenz auf ein Array, # das muss etwas anders behandelt werden als ein normales Array. # das Array sortieren und gleichzeitig eine Kopie anlegen: my @copy=sort(@$array_ref); # wenn man ein Array in Doppelte Anführungszeichen setzt, # dann fügt Perl dort die elemnte der liste ein. # man kann also schreiben my $key="@copy"; # und bekommt einen string den man als Schlüssel verwenden kann. # nun wird geprüft ob der String als Schlüssel noch nicht im Hash ist: if(!$unique{$key}) { # setze den Schlüssel, # damit ein Array mit den selben Werten nicht nochmal eingefügt wird. $unique{$key}=1; #füge das Array @unique_array hinzu: push(@unique_array,\@copy); # hier ist es wichtig eine Refenz hinzu zu fügen! } } # in @unique_array sind nun Arrayrefenzen mit einzigartigen Wertkombinationen
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# gegeben sei ein Array mit Arrays: my @array=( [1], [1 3 4], [1 2 3 4], [1 2 3 4], [2 3 1 4], [4 3 1], ); my %unique; my @unique_array=grep{$unique{"".join " ", sort @$_}++}@array; # in @unique_array sind nun Arrayrefenzen mit einzigartigen Wertkombinationen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
my @hand = qw (1 2 4 8); # nicht verändern
my @ch = @hand; # die liste der chancen
my $sum = 0;
for (@hand)
{
$sum += $_;
}
for (@hand)
{
$k = $_;
for (0..$#ch)
{
my $pu = $k + $ch[$_];
push (@ch, $pu) unless $pu > $sum;
}
say "@ch\n";
# jetzt sortieren und doppelte raus
1
2
3
4
5
6
7
8
9
10
11
my @hand = qw (a b c d);
my @ch = @hand;
for (@hand)
{
$k = $_;
for (0..$#ch)
{
push (@ch, $k.$ch[$_]) unless $ch[$_] =~ /$k/;
}
say "@ch\n";
}
1 2 3 4 5 6 7 8 9 10 11 12
my @hand = qw (a b c d); my @ch = @hand; for (@hand) { $k = $_; for (0..$#ch) { push (@ch, $k.$ch[$_]) unless $ch[$_] =~ /$k/; } } say "@ch\n";
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#!/usr/bin/perl use strict; use warnings; my @hand = qw (a b c d); my @ch; for my $k (@hand) { push(@ch,$k); for my $lst (@ch) { push (@ch, $k.$lst) if index($lst,$k)==-1; } } print join("\n",@ch)."\n";
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#!/usr/bin/perl use strict; use warnings; my @hand = qw(a b c d); # Liste mit den Ergebnissen my @ch; # gehe die POSITIONEN in der Hand durch for my $p (0..$#hand) { # füge die Position in @ch ein push(@ch,[$p]); # gehe alle Elemnte in @ch durch for my $elm (@ch) { # hole die Liste aus @$lem # ist eine Kopie my @l=@$elm; # schaue in der Liste nach, ob die Position schon drin ist unless(grep{$p==$_}@l) { # füge die Position zur Liste hinzu push(@l,$p); # sortiere es # ist dann später übersichtlicher :-) @l=sort(@l); #füge diese Kombination als neue hinzu push (@ch, \@l); } } } ############## #Ausgabe: #### ############## # gehe alles durch for my $c (@ch) { # gehe die einzelne Kombination durch for my $cc (@$c) { print $hand[$cc]." "; } print "\n"; }
1
2
3
4
5
6
7
8
for my $k (@hand)
{
push(@ch,$k);
for my $lst (@ch)
{
push (@ch, $k.$lst) if index($lst,$k)==-1;
}
}