Skip to content

На PascalABC.NET не решаются некоторые задачи с сайта acmp.ru #2647

Description

@fyodor-menshikov

На сайте решения олимпиадных задач acmp.ru есть несколько компиляторов Паскаля: PascalABC.NET 3.8, Free Pascal 3.2.2, Delphi 7.0.

Один и тот же код решения интерактивной задачи получает Accepted (принято) на Free Pascal и Delphi и Presentation Error 1 (ошибка представления на первом тесте) на PascalABC.NET. Судя по продолжительному статусу Running (исполняется) при сдаче, какая-то сторона не может дождаться данных от другой - или интерактор от решения, скомпилированного PascalABC.NET, или наоборот.

При замене чтения данных с readln(c); на c := Console.ReadLine()[1]; программа получает Accepted (принято). То есть есть основания предполагать, что readln пытается прочитать больше символов, чем сейчас доступно для чтения - и блокируется - а потом программу снимают по пределу времени.

Для версии PascalABC.NET 3.5.1 (которая была на сайте до 29.05.2020) есть решения интерактивных задач, которые используют readln. То есть проблемы в 3.5.1 точно нет. В 3.8 и актуальной 3.8.3 проблема есть.

Предположительно в какой-то версии PascalABC.NET после 3.5.1 происходило ускорение ввода - и это ускорение ввода читает слишком много символов вперёд - и это приводит к зависанию решений интерактивных задач. Альтернативно (но менее вероятно) flush(output); перестал выполнять свою функцию. Менее вероятно, потому что при чтении через Console.ReadLine() программа успешно работает без необходимости flush(output);.

Ссылка на условие интерактивной задачи и возможность сдать: https://acmp.ru/index.asp?main=task&id_task=1465

Полный код решения интерактивной задачи на классическом Паскале (принимается на Free Pascal и Delphi, не принимается на PascalABC.NET).

var
  mid, left, right: integer;
  c: char;
  
begin
  left := 0; // left < answer
  right := 1000 * 1000 * 1000 + 1; // right > answer
  while true do
  begin
    mid := (left + right) div 2;
    writeln(mid);
    flush(output);
    readln(c);
    if c = '<' then begin
      right := mid;
    end
    else if c = '>' then begin
      left := mid;
    end
    else if c = '=' then begin
      exit;
    end
    else begin
      writeln('неожиданный символ - >', c, '<');
      halt(1);
    end;
  end;
end.

Полный код решения, используя чтение .NET - принимается даже несмотря на отсутствие сброса буфера потока output.

var
  mid, left, right: integer;
  c: char;
  
begin
  left := 0; // left < answer
  right := 1000 * 1000 * 1000 + 1; // right > answer
  while true do
  begin
    mid := (left + right) div 2;
    writeln(mid);
    c := Console.ReadLine()[1];
    if c = '<' then begin
      right := mid;
    end
    else if c = '>' then begin
      left := mid;
    end
    else if c = '=' then begin
      exit;
    end
    else begin
      writeln('неожиданный символ - >', c, '<');
      halt(1);
    end;
  end;
end.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions