{ ACM International Collegiate Programming Contest Central European Regional Contest 2000 Problem H - Hotline Martin Kacer } Program Dialogue; Const MAX_WORD = 32; MAX_OBJECT = 64; MAX_STMENTS = 254; MAX_ROW = 254; Type TName = String [MAX_WORD]; TObject = String [MAX_OBJECT]; TOneRow = String [MAX_ROW]; TStment = Record Pos : Boolean; Subj, Verb : TName; Obj : TObject; End; Var TaskCnt, TaskNum : Integer; Stments : Array [1..MAX_STMENTS] of TStment; StmentCnt : Integer; Contradiction : Boolean; Row : TOneRow; SubjectYou : TName = 'you'; SubjectAny : TName = 'somebody'; Function SubjMatch (S1, S2 : TName) : Boolean; Begin SubjMatch:= (S1 = S2) or (S2 = 'everybody'); End; Procedure SwapYouAndMe (Var S : TName); Begin If (S = 'you') then S:= 'I' else If (S = 'I') then S:= 'you'; End; Procedure RemoveSFromEnd (Var Subj, Verb : TName); Begin If (Subj <> 'I') and (Subj <> 'you') then Begin If (Verb [Length(Verb)] = 's') then Verb:= Copy (Verb, 1, Length (Verb) - 1); End; End; { RemoveSFromEnd } Procedure AppendSToEnd (Var Subj, Verb : TName); Begin If (Subj <> 'I') and (Subj <> 'you') then Verb:= Verb + 's'; End; { AppendSToEnd } Procedure FormRightVerb (Var Subj, Verb : TName; Neg : Boolean); Begin If ( Neg ) then Begin If (Subj <> 'I') and (Subj <> 'you') then Verb:= 'doesn''t ' + Verb else Verb:= 'don''t ' + Verb; End else AppendSToEnd (Subj, Verb); End; Procedure ParseThreeWords (Var Row : TOneRow; Var Sp1, Sp2, Sp3 : Integer; Var W1, W2, W3 : TName); Begin Sp1:= 1; While (Row[Sp1] <> ' ') do Sp1:= Sp1 + 1; Sp2:= Sp1 + 1; While not (Row[Sp2] in [' ','.','?']) do Sp2:= Sp2 + 1; Sp3:= Sp2 + 1; If (Sp2 = Length (Row)) then Sp3:= Sp2; While not (Row[Sp3] in [' ','.','?']) do Sp3:= Sp3 + 1; W1:= Copy (Row, 1, Sp1-1); W2:= Copy (Row, Sp1+1, Sp2-Sp1-1); W3:= ''; If (Sp3 > Sp2) then W3:= Copy (Row, Sp2+1, Sp3-Sp2-1); {WriteLn ('DEBUG: PARSE: w1=''',W1,''',w2=''',W2,''',w3=''',W3,'''');} End; Procedure OneStatement (Row : TOneRow); Var Sp1, Sp2, Sp3 : Integer; W1, W2, W3 : TName; ObjIdx : Integer; I : Integer; Begin ParseThreeWords (Row, Sp1, Sp2, Sp3, W1, W2, W3); StmentCnt:= StmentCnt + 1; With Stments[StmentCnt] do Begin Pos:= true; Subj:= W1; Verb:= W2; Obj:= ''; ObjIdx:= Sp2; If (Verb = 'don''t') or (Verb = 'doesn''t') then Begin Pos:= false; Verb:= W3; ObjIdx:= Sp3; End else RemoveSFromEnd (W1, Verb); If (W1 = 'nobody') then Begin Pos:= false; Subj:= 'everybody'; End; If (ObjIdx < Length (Row)) then Obj:= Copy (Row, ObjIdx, Length(Row) - ObjIdx); {WriteLn ('DEBUG: STATEMENT: pos=', Pos, ', subj=''', Subj, ''', verb=''', Verb, ''', obj=''', Obj, '''');} End; If (StmentCnt > 1) then For I:= 1 to StmentCnt-1 do If (SubjMatch (Stments[I].Subj, Stments[StmentCnt].Subj)) or (SubjMatch (Stments[StmentCnt].Subj, Stments[I].Subj)) then If (Stments[I].Verb = Stments[StmentCnt].Verb) and (Stments[I].Obj = Stments[StmentCnt].Obj) and (Stments[I].Pos <> Stments[StmentCnt].Pos) then Begin Contradiction:= true; {WriteLn ('DEBUG: CONTRADICTION with statement ', I);} End; End; { OneStatement } Procedure OneQuestionYesNo (Row : TOneRow); Var Sp1, Sp2, Sp3 : Integer; W1, W2, W3 : TName; ObjIdx : Integer; I : Integer; SubjQ, VerbQ : TName; ObjQ : TObject; NegReply, Reply : Boolean; Begin ParseThreeWords (Row, Sp1, Sp2, Sp3, W1, W2, W3); ObjIdx:= Sp3; SubjQ:= W2; VerbQ:= W3; ObjQ:= ''; If (ObjIdx < Length (Row)) then ObjQ:= Copy (Row, ObjIdx, Length(Row) - ObjIdx); RemoveSFromEnd (SubjQ, VerbQ); {WriteLn ('DEBUG: YESNO QUERY: subj=''', SubjQ, ''', verb=''', VerbQ, ''', obj=''', ObjQ, '''');} Reply:= false; NegReply:= false; If (StmentCnt > 0) then For I:= 1 to StmentCnt do With Stments[I] do If (SubjQ = 'anybody') or (SubjMatch (SubjQ, Subj)) then If (VerbQ = Verb) and (ObjQ = Obj) then If (Pos) then Reply:= true else NegReply:= true; SwapYouAndMe (SubjQ); FormRightVerb (SubjQ, VerbQ, NegReply); If ( NegReply ) then WriteLn ('no, ', SubjQ, ' ', VerbQ, ObjQ, '.') else If ( Reply ) then WriteLn ('yes, ', SubjQ, ' ', VerbQ, ObjQ, '.') else WriteLn ('maybe.'); End; { OneQuestionYesNo } Procedure OneQuestionWho (Row : TOneRow); Var Sp1, Sp2, Sp3 : Integer; W1, W2, W3 : TName; ObjIdx : Integer; I : Integer; VerbQ : TName; ObjQ : TObject; Replies : Array [1..MAX_STMENTS] of TName; ReplCnt : Integer; NegReply, PosReply : Boolean; EveryReply : Boolean; Begin ParseThreeWords (Row, Sp1, Sp2, Sp3, W1, W2, W3); ObjIdx:= Sp2; VerbQ:= W2; ObjQ:= ''; If (ObjIdx < Length (Row)) then ObjQ:= Copy (Row, ObjIdx, Length(Row) - ObjIdx); RemoveSFromEnd (SubjectAny, VerbQ); {WriteLn ('DEBUG: WHO QUERY: verb=''', VerbQ, ''', obj=''', ObjQ, '''');} ReplCnt:= 0; NegReply:= false; PosReply:= false; EveryReply:= false; If (StmentCnt > 0) then For I:= 1 to StmentCnt do With Stments[I] do If (VerbQ = Verb) and (ObjQ = Obj) then Begin If (Pos) then Begin PosReply:= true; If (Subj = 'everybody') then EveryReply:= true else If (Subj <> 'somebody') then Begin ReplCnt:= ReplCnt + 1; Replies[ReplCnt]:= Subj; SwapYouAndMe (Replies[ReplCnt]); End; End else If (Subj = 'everybody') then NegReply:= true; End; If (NegReply) then Begin FormRightVerb (SubjectAny, VerbQ, false); WriteLn ('nobody ', VerbQ, ObjQ, '.'); End else If (EveryReply) then Begin FormRightVerb (SubjectAny, VerbQ, false); WriteLn ('everybody ', VerbQ, ObjQ, '.'); End else If (PosReply) then Begin If (ReplCnt = 0) then Begin ReplCnt:= 1; Replies[1]:= 'somebody'; End; For I:= 1 to ReplCnt do Begin If (I > 1) and (I = ReplCnt) then Write (' and ') else If (I > 2) then Write (', '); Write (Replies[I]); End; If (ReplCnt = 1) then FormRightVerb (Replies[1], VerbQ, false) else FormRightVerb (SubjectYou, VerbQ, false); WriteLn (' ', VerbQ, ObjQ, '.'); End else WriteLn ('I don''t know.'); End; { OneQuestionWho } Procedure OneQuestionWhat (Row : TOneRow); Var Sp1, Sp2, Sp3 : Integer; W1, W2, W3 : TName; SubjQ, VerbQ : TName; I, J : Integer; Replies : Array [1..MAX_STMENTS] of Integer; ReplCnt : Integer; Dupl : Boolean; Begin ParseThreeWords (Row, Sp1, Sp2, Sp3, W1, W2, W3); SubjQ:= W3; {WriteLn ('DEBUG: WHAT QUERY: subj=''', SubjQ);} ReplCnt:= 0; If (StmentCnt > 0) then For I:= 1 to StmentCnt do With Stments[I] do If (SubjMatch (SubjQ, Subj)) then Begin Dupl:= false; If (ReplCnt > 0) then For J:= 1 to ReplCnt do If (Verb = Stments[Replies[J]].Verb) and (Obj = Stments[Replies[J]].Obj) then Dupl:= true; If (not Dupl) then Begin ReplCnt:= ReplCnt + 1; Replies[ReplCnt]:= I; End; End; SwapYouAndMe (SubjQ); If (ReplCnt = 0) then WriteLn ('I don''t know.') else Begin Write (SubjQ, ' '); For I:= 1 to ReplCnt do Begin If (I > 1) and (I = ReplCnt) then Write (', and ') else If (I > 1) then Write (', '); VerbQ:= Stments[Replies[I]].Verb; FormRightVerb (SubjQ, VerbQ, not Stments[Replies[I]].Pos); Write (VerbQ, Stments[Replies[I]].Obj); End; WriteLn ('.'); End; End; { OneQuestionWhat } Begin Readln (TaskCnt); For TaskNum:= 1 to TaskCnt do Begin StmentCnt:= 0; Contradiction:= false; WriteLn ('Dialogue #', TaskNum:1, ':'); ReadLn (Row); While (Row[Length(Row)] <> '!') do Begin If (Row[Length(Row)] = '.') then OneStatement (Row) else Begin WriteLn (Row); If (Contradiction) then WriteLn ('I am abroad.') else If (Copy (Row, 1, 4) = 'who ') then OneQuestionWho (Row) else If (Copy (Row, 1, 5) = 'what ') then OneQuestionWhat (Row) else OneQuestionYesNo (Row); WriteLn; End; ReadLn (Row); End; WriteLn (Row); WriteLn; End; End.