summaryrefslogtreecommitdiff
path: root/fpcsrc/tests/bench/shootout/src/fannkuch.pp
blob: 66a773f245eaa8e750b1400e1045776c06ee119e (plain)
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
program fannkuch;
{ The Computer Language Shootout
  http://shootout.alioth.debian.org/

  contributed by Florian Klaempfl
  modified by Micha Nelissen
  modified by Vincent Snijders
  modified by Steve Fisher

  Compile with
  fpc -O3 fannkuch.pp
}

{$INLINE ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}

type
    TIntegerArray = Array[0..99] of longint;

var
   permu, permu_copy, count: TIntegerArray;
   r, n, answer: longint;

procedure swap(var a, b: longint); inline;
var  tmp: longint;
begin  tmp := a;  a := b;  b := tmp   end;

procedure reverse( k: longint); inline;
var
  pi, pj : pLongint;
begin
  pi := @permu_copy[1];
  pj := @permu_copy[k-1];
  while pi<pj do
  begin
    swap(pi^, pj^);
    inc(pi);
    dec(pj);
  end;
end;

function countflips: longint; inline;
var
  last: LongInt;
  tmp: LongInt;
begin
  countflips := 0;
  last := permu_copy[0];
  repeat
    // Reverse part of the array.
    reverse(last);

    tmp := permu_copy[last];
    permu_copy[last] := last;
    last := tmp;
    inc(countflips);
  until last = 0;
end;

function NextPermutation: boolean;
var
  tmp: LongInt;
  i : longint;
begin
  NextPermutation := true;
  repeat
    if r = n then
    begin
      NextPermutation := false;
      break;
    end;
    tmp := permu[0];
    for i := 1 to r do
      permu[i-1] := permu[i];
    permu[r] := tmp;

    dec(count[r]);
    if count[r] > 0 then
      break;
    inc(r);
  until false;
end;

function fannkuch: longint;
var
  print30, m, i, flips: longint;
begin
  print30 := 0;
  fannkuch := 0;
  m := n - 1;

  // Initial permutation.
  for i := 0 to m do   permu[i] := i;

  r := n;
  repeat
    if print30 < 30 then
    begin
      for i := 0 to m do
        write(permu[i] + 1);
      writeln;
      inc(print30);
    end;
    while r <> 1 do
    begin
      count[r-1] := r;
      dec(r);
    end;
    if (permu[0]<>0) and (permu[m]<>m) then
    begin
      move(permu[0], permu_copy[0], sizeof(longint)*n);
      flips := countflips;
      if flips > fannkuch then
        fannkuch := flips;
    end;
  until not NextPermutation;
end;

begin
  n := 7;
  if paramCount() = 1 then
    Val(ParamStr(1), n);
  answer := fannkuch;
  writeln('Pfannkuchen(', n, ') = ', answer);
end.