Описание Имеется таблица M×N, в каждой ячейке которой записано либо целое число, либо арифметическая формула. В формулах могут присутствовать целые числа, знаки "*", "/", "+", "-", "(", ")", пробелы и ссылки на значения из других ячеек таблицы, записываемые в виде {НомерСтроки, НомерСтолбца}, например {1,10}
Задание Требуется вычислить значения во всех ячейках заданной таблицы
Входные данные В первой строке входного файла записаны целые числа М и N (1≤M,N≤20). В каждой из последующих М строк содержится описание очередной строки таблицы. Описание состоит из целых чисел и арифметических формул, разделенных символами "|" (ASCII-код 124). Все числа принадлежат диапазону [-32768, 32767], а длина каждой формулы не превышает 100 символов
Выходные данные Выведите в выходной файл значения всех ячеек таблицы. Значения ячеек каждой строки таблицы должны быть записаны через пробел в отдельной строке выходного файла. Все значения следует выводить с точностью до двух знаков после десятичной точки. Если значение ячейки вычислить невозможно, вместо него следует вывести символ "-" (ASCII-код 45)
Решение {$A+,B-,D+,E+,F-,G+,I+,L+,N+,O-,P-,Q-,R-,S-,T-,V-,X+,Y+} {$M 65520,0,655360} Program spreadsheet; Const InFile='spsheet.in'; OutFile='spsheet.out'; MaxMN=20; MaxCell=MaxMN*MaxMN; Eps=1E-8; Type Real=Extended; TElem=String[102]; TOffersArr=Array[0..MaxCell-1,0..MaxCell Div 8]Of Byte; TOffNumArr=Array[0..MaxCell-1]Of Word; Var M,N,Cells:Word; Elems:Array[0..MaxCell-1]Of TElem; Value:Array[0..MaxCell-1]Of Real; Ok:Array[0..MaxCell-1]Of Boolean; Div0:Array[0..MaxCell-1]Of Boolean; Offers:^TOffersArr; ONum:TOffNumArr; DivBy0:Boolean; S:String; Ps:Byte; Function CellByXY(X,Y:Byte):Word; Begin CellByXY:=Word(Y-1)*M+X-1; End; Procedure CellToXY(C:Word; Var X,Y:Byte); Begin Y:=C Div M+1; X:=C Mod M+1; End; Function GetOffers(C1,C2:Byte):Boolean; Begin GetOffers:=Offers^[C1,C2 Shr 3] And (1 Shl (C2 And $7))>0; End; Procedure SetOffer(C1,C2:Byte); Begin Offers^[C1,C2 Shr 3]:=Offers^[C1,C2 Shr 3] Or (1 Shl (C2 And $7)); Inc(ONum[C1]); End; Procedure Load; Var I,J:Byte; Ch:Char; Cur:TElem; Begin New(Offers); Assign(Input,InFile); ReSet(Input); ReadLn(N,M); For I:=1 To N DoBegin For J:=1 To M DoBegin Cur:=''; Repeat Read(Ch); Case Ch Of ' ',#9,'|':; Else Cur:=Cur+Ch; End; Until (Ch='|') Or EOLN; Elems[CellByXY(J,I)]:=Cur; End; ReadLn; End; Close(Input); Cells:=M*N; End; Procedure FillOffers; Var I,J:Word; X,Y:Byte; AS,S1,S2:String[6]; Begin FillChar(Offers^,SizeOf(Offers^),0); FillChar(ONum,SizeOf(ONum),0); For I:=0 To Cells-1 DoBegin CellToXY(I,X,Y); Str(X,S1); Str(Y,S2); AS:='{'+S2+','+S1+'}'; For J:=0 To Cells-1 DoIf Pos(AS,Elems[J])>0 Then SetOffer(J,I); End; End; Function Expression:Real; Forward; Function Multiplicator:Real; Var Result:Real; II:Byte; AX,AY:Byte; Cnt:Integer; Begin Case S[Ps] Of '{':Begin Inc(Ps); II:=Ps; While (S[Ps]>='0') And (S[Ps]<='9') Do Inc(Ps); Val(Copy(S,II,Ps-II),AY,Cnt); Inc(Ps); II:=Ps; While (S[Ps]>='0') And (S[Ps]<='9') Do Inc(Ps); Val(Copy(S,II,Ps-II),AX,Cnt); Result:=Value[CellByXY(AX,AY)]; Inc(Ps); If Div0[CellByXY(AX,AY)] Then DivBy0:=True; End; '0'..'9':Begin II:=Ps; While (S[Ps]>='0') And (S[Ps]<='9') Do Inc(Ps); Val(Copy(S,II,Ps-II),Result,Cnt); End; '-':Begin Inc(Ps); Result:=-Multiplicator; End; '+':Begin Inc(Ps); Result:=Multiplicator; End; '(':Begin Inc(Ps); Result:=Expression; Inc(Ps); End; End; Multiplicator:=Result; End; Function Additional:Real; Var Result:Real; Temp:Real; Begin Result:=Multiplicator; While (S[Ps]='*') Or (S[Ps]='/') DoBegin Inc(Ps); Case S[Ps-1] Of '*':Result:=Result*Multiplicator; '/':Begin Temp:=Multiplicator; If Abs(Temp)Then Begin DivBy0:=True; Break; EndElse Result:=Result/Temp; End; End; End; Additional:=Result; End; Function Expression:Real; Var Result:Real; Begin Result:=Additional; While (S[Ps]='+') Or (S[Ps]='-') DoBegin If DivBy0 Then Break; Inc(Ps); Case S[Ps-1] Of '+':Result:=Result+Additional; '-':Result:=Result-Additional; End; End; Expression:=Result; End; Procedure Solve; Var I,J:Word; Final:Boolean; Begin FillChar(Ok,SizeOf(Ok),True); FillChar(Div0,SizeOf(Div0),False); Repeat Final:=True; For I:=0 To Cells-1 DoIf Ok[I] And (ONum[I]=0) ThenBegin S:=Elems[I]+#0; Ps:=1; DivBy0:=False; Value[I]:=Expression; Div0[I]:=DivBy0; Ok[I]:=False; For J:=0 To Cells-1 Do If Ok[J] And GetOffers(J,I) Then Dec(ONum[J]); Final:=False; End; Until Final; End; Procedure Save; Var I,J:Byte; Begin Assign(Output,OutFile); ReWrite(Output); For I:=1 To N DoBegin For J:=1 To M DoBegin If J>1 ThenWrite(' '); If Ok[CellByXY(J,I)] Or Div0[CellByXY(J,I)] ThenWrite('-') ElseWrite(Value[CellByXY(J,I)]:0:2); End; WriteLn; End; Close(Output); Dispose(Offers); End; Begin Load; FillOffers; Solve; Save; End.