ソースを参照

Texts.Store; Olympic example

Arthur Yefimov 3 年 前
コミット
bc87bcc148
2 ファイル変更109 行追加4 行削除
  1. 83 0
      Programs/FunGame.Mod
  2. 26 4
      src/Texts.Mod

+ 83 - 0
Programs/FunGame.Mod

@@ -0,0 +1,83 @@
+MODULE FunGame;
+IMPORT Texts, Out;
+
+PROCEDURE LastBit(x: INTEGER): INTEGER;
+VAR k: INTEGER;
+BEGIN k := 1;
+  WHILE k <= x DO k := k * 2 END
+RETURN k DIV 2 END LastBit;
+
+PROCEDURE Rotate(x, k: INTEGER): INTEGER;
+RETURN x DIV 2 + ORD(ODD(x)) * k END Rotate;
+
+PROCEDURE Parse(x: INTEGER): INTEGER;
+VAR x0, k, max: INTEGER;
+BEGIN
+  x0 := x; max := x;
+  k := LastBit(x); (* k - максимальная степень двойки такая, что k <= x *)
+  REPEAT
+    x := Rotate(x, k);
+    Out.Int(x, 10); Out.Ln;
+    IF x > max THEN max := x END
+  UNTIL x = x0
+RETURN max END Parse;
+
+PROCEDURE Do;
+VAR T: Texts.Text;
+  S: Texts.Scanner;
+  W: Texts.Writer;
+  n: INTEGER;
+BEGIN
+  NEW(T); Texts.Open(T, 'fungame.in'); Texts.OpenScanner(S, T, 0);
+  Texts.Scan(S); n := S.i;
+  n := Parse(n);
+  Texts.Open(T, ''); Texts.OpenWriter(W);
+  Texts.WriteInt(W, n, 0); Texts.WriteLn(W);
+  Texts.Append(T, W.buf); Texts.Close(T, 'fungame.out')
+END Do;
+
+BEGIN
+  Do
+END FunGame.
+
+
+                  Забавная игра
+                  ~~~~~~~~~~~~~
+
+Задача D заочного тура Московской олимпиады по программированию, 2003.
+
+Время на тест - 1 секунда.
+
+Легендарный учитель математики Юрий Петрович придумал забавную игру с
+числами. А именно, взяв произвольное целое число, он переводит его в двоичную
+систему счисления, получая некоторую последовательность из нулей и единиц,
+начинающуюся с единицы (Например, десятичное число 19 в двоичной системе
+запишется как 10011). Затем учитель начинает сдвигать цифры полученного
+двоичного числа по циклу (так, что последняя цифра становится первой, а все
+остальные сдвигаются на одну позицию вправо), выписывая образующиеся при этом
+последовательности из нулей и единиц в столбик - он подметил, что независимо
+от выбора исходного числа получающиеся последовательности начинают с
+некоторого момента повторяться. И, наконец, Юрий Петрович отыскивает
+максимальное из выписанных чисел и переводит его обратно в десятичную систему
+счисления, считая это число результатом проделанных манипуляций. Так, для
+числа 19 список последовательностей будет таким:
+
+     10011
+     11001
+     11100
+     01110
+     00111
+     10011
+
+и результатом игры, следовательно, окажется число 28 (11100[2]). Поскольку
+придуманная игра с числами все больше занимает воображение учителя, отвлекая
+тем самым его от работы с ну очень одаренными школьниками, вас просят
+написать программу, которая бы помогла Юрию Петровичу получать результат игры
+без утомительных ручных вычислений.
+
+Входные данные:
+  Программа получает на вход единственное натуральное число,
+  не превосходящее 10^9.
+
+Выходные данные:
+  Программа должна вывести единственное натуральное число - результат игры.

+ 26 - 4
src/Texts.Mod

@@ -49,10 +49,6 @@ BEGIN T.f := Files.Old(fname);
   T.len := SYSTEM.SHORT(Files.Length(T.f)); T.changed := FALSE
 END Open;
 
-PROCEDURE Close*(T: Text);
-BEGIN IF (T.f # NIL) & T.changed THEN Files.Register(T.f) END
-END Close;
-
 PROCEDURE OpenReader*(VAR R: Reader; T: Text; pos: INTEGER);
 BEGIN Files.Set(R.rider, T.f, pos); R.eot := FALSE
 END OpenReader;
@@ -70,6 +66,18 @@ BEGIN Files.ReadChar(S.rider, S.nextCh);
   IF ~S.rider.eof & (S.nextCh = 0AX) THEN INC(S.line) END
 END Next;
 
+PROCEDURE Store(VAR W: Files.Rider; T: Text);
+VAR ch: CHAR;
+  R: Reader;
+BEGIN OpenReader(R, T, 0); Read(R, ch);
+  WHILE ~R.eot DO Files.WriteChar(W, ch); Read(R, ch) END
+END Store;
+
+PROCEDURE Close*(T: Text; name: ARRAY OF CHAR);
+VAR F: Files.File; W: Files.Rider;
+BEGIN F := Files.New(name); Files.Set(W, F, 0); Store(W, T); Files.Register(F)
+END Close;
+
 PROCEDURE OpenScanner*(VAR S: Scanner; T: Text; pos: INTEGER);
 BEGIN OpenReader(S, T, pos); S.line := 0; S.nextCh := ' '
 END OpenScanner;
@@ -241,6 +249,20 @@ BEGIN Files.Set(R, SB.f, 0); Files.Set(W, DB.f, DB.len); n := SB.len;
   INC(DB.len, SB.len)
 END Copy;
 
+PROCEDURE Delete*(T: Text; beg, end: INTEGER; B: Buffer);
+VAR ch: CHAR;
+  n: INTEGER;
+  R, W: Files.Rider;
+BEGIN
+  IF beg < 0 THEN beg := 0 END;
+  IF end > T.len THEN end := T.len END;
+  IF beg < end THEN
+    (*!FIXME rewrite*)
+    Files.Set(W, T.f, beg); Files.Set(R, T.f, end); n := T.len - end;
+    WHILE n # 0 DO Files.ReadChar(R, ch); Files.WriteChar(W, ch); DEC(n) END
+  END
+END Delete;
+
 PROCEDURE Insert*(T: Text; pos: INTEGER; B: Buffer);
 VAR R, W: Files.Rider;
   ch: CHAR;