1+ program Zeckendorf;
2+
3+ { $mode objfpc}{ $H+}{ $J-}{ $modeswitch advancedrecords}
4+
5+ uses
6+ SysUtils;
7+
8+ const
9+ MAX_FIB_COUNT = { $IFDEF CPU64} 92 { $ELSE} 46 { $ENDIF} ;
10+
11+ type
12+ TNatural = { $IFDEF CPU64} UInt64{ $ELSE} UInt32{ $ENDIF} ;
13+
14+ TZeckendorf = record
15+ private
16+ FFibonacciTable: array [0 ..MAX_FIB_COUNT - 1 ] of TNatural;
17+ FActualCount: Integer;
18+ FInitialized: Boolean;
19+ procedure Initialize ;
20+ public
21+ procedure DecomposeAndPrint (ANumber: TNatural);
22+ end ;
23+
24+ procedure TZeckendorf.Initialize ;
25+ var
26+ A, B, Next: TNatural;
27+ begin
28+ if FInitialized then Exit;
29+
30+ FFibonacciTable[0 ] := 1 ;
31+ FFibonacciTable[1 ] := 2 ;
32+ FActualCount := 2 ;
33+ A := 1 ;
34+ B := 2 ;
35+
36+ while (High(TNatural) - A >= B) and (FActualCount < MAX_FIB_COUNT) do
37+ begin
38+ Next := A + B;
39+ FFibonacciTable[FActualCount] := Next;
40+ Inc(FActualCount);
41+ A := B;
42+ B := Next;
43+ end ;
44+ FInitialized := True;
45+ end ;
46+
47+ procedure TZeckendorf.DecomposeAndPrint (ANumber: TNatural);
48+ var
49+ I: Integer;
50+ IsFirstTerm: Boolean;
51+ begin
52+ Initialize;
53+
54+ if ANumber = 0 then Exit;
55+
56+ IsFirstTerm := True;
57+ for I := FActualCount - 1 downto 0 do
58+ begin
59+ if FFibonacciTable[I] <= ANumber then
60+ begin
61+ if not IsFirstTerm then Write(' , ' ) else IsFirstTerm := False;
62+ Write(FFibonacciTable[I]);
63+ Dec(ANumber, FFibonacciTable[I]);
64+ end ;
65+ if ANumber = 0 then Break;
66+ end ;
67+ WriteLn;
68+ end ;
69+
70+ procedure ShowUsage ;
71+ begin
72+ WriteLn(' Usage: please input a non-negative integer' );
73+ Halt(1 );
74+ end ;
75+
76+ var
77+ InputVal: TNatural;
78+ Code: Integer;
79+ Z: TZeckendorf;
80+ begin
81+ if (ParamCount <> 1 ) then ShowUsage;
82+
83+ Val(ParamStr(1 ), InputVal, Code);
84+ if (Code <> 0 ) or (Pos(' -' , ParamStr(1 )) > 0 ) then ShowUsage;
85+
86+ if InputVal = 0 then
87+ WriteLn
88+ else
89+ Z.DecomposeAndPrint(InputVal);
90+ end .
0 commit comments