## Einige GAP Beispiele zum Arbeiten mit Listen in GAP
#   gap> l := [1,2,3];
#   [ 1, 2, 3 ]
#   gap> ll := [1, Group((1,2,3)), (1,2), [42,43]];
#   [ 1, Group([ (1,2,3) ]), (1,2), [ 42, 43 ] ]
#   gap> ll[3] in ll[2];
#   false
#   gap> [1..5] = [1,2,3,4,5];
#   true
#   gap> for i in [3..7] do Print(i, " "); od;
#   3 4 5 6 7 
#   gap> l;
#   [ 1, 2, 3 ]
#   gap> Add(l, 7);
#   gap> l;
#   [ 1, 2, 3, 7 ]
#   gap> Append(l, [12,-2]);
#   gap> l;
#   [ 1, 2, 3, 7, 12, -2 ]
#   gap> Length(l);
#   6
#   gap> Remove(l);
#   -2
#   gap> l;
#   [ 1, 2, 3, 7, 12 ]
#   gap> 7 in l;
#   true

# Zu Aufgabe 5:

ZyklenSchreibweise := function(perm)
  local n, gefunden, zykeln, zyk, i, j;
  n := LargestMovedPoint(perm); # oder n als Eingabe vorgeben

  # zum Merken, welche Punkte schon gesehen wurden
  gefunden := BlistList([1..12],[]);
  ##  dies ist eine bessere Version von, siehe '?BlistList'
  #gefunden := List([1..n], i-> false);

  # Liste für das Ergebnis
  zykeln := [];

  for i in [1..n] do
    if not gefunden[i] then
      gefunden[i] := true;
      # finde Zykel, der i enthält
      zyk := [i];
      j := i^perm;
      while j <> i do
        Add(zyk, j);
        gefunden[j] := true;
        j := j^perm;
      od;
      # schreiben nur Zykel der Länge > 1 in Ergebnis
      if Length(zyk) > 1 then
        Add(zykeln, zyk);
      fi;
    fi;
  od;

  # Ergebnis zurückgeben
  return zykeln;
end;

# Test
s9 := SymmetricGroup(9);
sum := 0;
for x in s9 do sum := sum + Length(ZyklenSchreibweise(x)); od; time;
sum;  # sollte 663696 rauskommen


# Zu Aufgabe 10:

# Argumente sind Gruppe G und Objekt m (auf dem g in G per m^g operiert)
Bahn := function(G, m)
  local X, Bahn, y, x, g;

  # Initialisierung
  X := GeneratorsOfGroup(G);
  Bahn := [m];

  # wende auf jedes Element der Bahn jeden Erzeuger an:
  for x in Bahn do
    for g in X do
      y := x^g;
      if not y in Bahn then
        # y ist noch nicht in Bahn, wird an Bahn angehängt
        Add(Bahn, y);
      fi;
    od;
  od;

  # Rückgabe ist Liste mit Objekten in der Bahn vom m
  return Bahn;
end;

# Testbeispiele siehe nach Aufgabe 15.

# Zu Aufgabe 15: 

# Argumente sind Gruppe G und Objekt m (auf dem g in G per m^g operiert)
BahnUndStabilisator := function(G, m)
  local X, Bahn, V, XS, j, x, y, k, g;

  # Initialisierung
  X := GeneratorsOfGroup(G);
  Bahn := [m];
  V := [One(G)];
  XS := [];
  j := 1;

  # wende auf jedes Element der Bahn jeden Erzeuger an:
  while j <= Length(Bahn) do
    x := Bahn[j];
    for g in X do
      y := x^g;
      k := Position(Bahn, y);
      if k = fail then
        # y ist noch nicht in Bahn
        Add(Bahn, y);
        # merken uns in V, dass y = m^(V[j]*g)
        Add(V, V[j]*g);
      else
        # y ist bereits in Bahn, finden Element in Stabilisator
        # (wir benutzen 'AddSet' statt 'Add' um mehrfache Einträge
        # zu vermeiden)
        AddSet(XS, V[j]*g/V[k]);
      fi;
    od;
    j := j+1;
  od;

  # Rückgabe ist Liste aus: Liste mit Objekten in der Bahn vom m und
  # Liste von Erzeugern von Stab_G(m).
  return [Bahn, XS];
end;

# Test
# Permutationsgruppe und Zahl aus N
bs1 := BahnUndStabilisator(SymmetricGroup(9),9);
Group(bs1[2]) = SymmetricGroup(8);

m24 := MathieuGroup(24);
bs2 := BahnUndStabilisator(m24, 3);
Size(m24);
stab := Group(bs2[2]);
Length(bs2[1]) * Size(stab);
Length(bs2[2]);
stab = Group(bs2[2][2], bs2[2][13]); # viele unnötige Erzeuger

LoadPackage("AtlasRep");
# MathieuGroup(22) als Matrixgruppe in GL(21, Z):
m22 := Group(AtlasGenerators("M22", 53).generators);
# ein Zeilenvektor in Z^21, Gruppe operiert durch Matrixmultiplikation
v := 0*[1..21];; v[1] := 1;; v[5] := -1;; v;

bs3 := BahnUndStabilisator(m22, v);
Length(bs3[1]);