Олимпиады по программированию

olympiads.ru

Олимпиады прошлых лет
2017/18
2016/17
2015/16
2014/15
2013/14
2012/13
2011/12
2010/11
2009/10
2008/09
2007/08
2006/07

IV открытая олимпиада школьников по программированию (2009/10)
Доска объявлений олимпиады
Информация об олимпиаде
Заключительный этап
Информация о заключительном этапе
Список приглашенных
Результаты заключительного этапа
Задачи, тесты
Персональные странички участников
Предварительное раписание
Система оценки решений на заключительном этапе
Информация для иногородних участников
Планируемое размещение иногородних
Как добраться
Заочный этап
Задачи, тесты
Регистрация
1 тур
Персональная страничка участника
Текущие результаты
2 тур
Персональная страничка участника
Текущие результаты
Примеры реализации ввода-вывода на разных языках
FAQ по работе с тестирующей системой
Связаться с оргкомитетом

Олимпиада проводится при поддержке Московского физико-технического института, Компьютерной компании НИКС, Компании Yandex

Информационная поддержка:
журнал "Мир ПК"

IV Открытая олимпиада школьников по программированию, 2009/10 учебный год

Особенности языков программирования и файловый ввод-вывод

Поскольку часто именно файловый ввод-вывод является основной проблемой начинающих участников олимпиад, мы подготовили небольшую памятку, демонстрирующую реализацию ввода-вывода на различных языках программирования.

Программа на любом языке программирования должна завершаться с кодом возврата 0. В частности, программа на C всегда должна заканчиваться оператором return 0; Имена входных и выходных файлов должны быть написаны маленькими латинскими буквами. Не забывайте закрывать выходной файл (иначе во многих языках он остается пустым).

Ввод-вывод будем демонстрировать на примере следующей задачи: в файле sum.in записаны два целых числа по модулю не превышающих 32000, в файл sum.out нужно вывести их сумму.

Примечание для программирующих на QBasic, Borland Pascal, Borland C: Жюри не гарантирует, что любую задачу олимпиады можно решить с использованием этих языков программирования.


Pascal, Delphi

Примечание для программирующих на Delphi: Имена стандартных модулей пишутся точно так же, как в документации (имеется в виду сочетание больших и маленьких букв) и только так. Например: Math, SysUtils.

var a,b:longint;
begin
assign(input,'sum.in');
reset(input);
assign(output,'sum.out');
rewrite(output);
read(a,b);
writeln(a+b);
close(input);
close(output);
end.

C

#include <stdio.h>

int main(void)
{
  long a, b;
  FILE *fin, *fout;
  fin = fopen("sum.in", "r");
  fout = fopen("sum.out", "w");
  fscanf(fin, "%ld%ld", &a, &b);
  fprintf(fout, "%ld", a + b);
  fclose(fin);
  fclose(fout);
  return 0;
}

Примечание для программирующих на GNU C/C++: При выводе значений переменных типа long long под ОС Windows нужно использовать спецификатор %I64d, а при сдаче решений на проверку (для ОС Linux) - спецификатор %lld. "Универсальный" код, который работает правильно под обеими системами, может выглядеть так:

#ifdef WIN32
	printf("%I64d\n",ans);
#else
	printf("%lld\n",ans);
#endif

C++

#include <fstream>

using namespace std;

int main ()
{
  long a, b;
  ifstream fin ("sum.in");
  ofstream fout ("sum.out");
  fin >> a >> b;
  fout << a + b << endl;
  fin.close ();
  fout.close ();
  return 0;
}

Java

Программа должна находиться в единственном классе с именем Main (обязательно с большой буквы), метод main должен находиться внутри класса Main. Вложенные классы допускаются.

import java.io.*;
public class Main
{
   public static void main(String[] args) throws Exception
   {
	StreamTokenizer in = new StreamTokenizer(
          new BufferedInputStream(
              new FileInputStream(new File("sum.in"))));
	PrintStream out = new PrintStream(new File("sum.out"));
		
	int a, b;
	in.nextToken(); a = (int) in.nval;
	in.nextToken(); b = (int) in.nval;
	out.println(a + b);
   }
}

QBasic

open "sum.in" for input as #1
open "sum.out" for output as #2
input #1,a,b
print #2,a+b
close #1
close #2

perl, php, python, ruby

В скриптовых языках perl, php, python, ruby отсутствует возможность потокового ввода данных, свойственного для языков Pascal, C и C++, то есть в этих языках нельзя простыми методами считать из входного файла последовательность целых чисел (действительных чисел, строк и т.д.), если неизвестно, находятся ли эти числа в одной строке или в разных строках.

Для ввода данных в этих языках предлагается считывать содержимое всего файла сразу в строковую переменную, а затем использовать стандартную функцию split для разбивки этой переменной на поля. Функция split игнорирует все начальные и конечные пробельные символы (то есть пробелы, символы табуляции и символы новой строки), а все прочие символы разбиваются на последовательности, состоящие из непробельных символов, пробельные символы являются разделителями для полученных последовательностей. В результате получается список, состоящий из строк непробельных символов, содержащихся в исходном файле. Например, если в исходном файле записана строка "1 2 abc" (количество пробелов неважно), то в полученном списке будет три элемента - "1", "2" и "abc".

В языке php имеется небольшое отличие - функция называется preg_split, при ее вызове в качестве аргумента необходимо явно указать регулярное выражение, которое задает разделитель полей (это /\s+/, в языках perl, python и ruby такое значение разделителя используется по умолчанию), и перед вызовом функции preg_split необходимо явно удалить начальные и концевые пробелы из строки функцией trim (в языках perl, python и ruby это делает сама функция split).

Можно пользоваться и другими способами ввода-вывода данных, поддерживаемых данными языками.

Ниже приведены примеры решения задачи "A+B" на языках perl, php, python, ruby.


perl

#!/usr/bin/perl -w

# Объявляем файлы FIN и FOUT для ввода-вывода данных
open(FIN, "<sum.in");
open(FOUT,">sum.out");

# В переменной $/ записан символ, который считается разделителем строк
# Удаление этой переменной приведет к тому, что весь файл будет считаться
# одной большой строкой.
undef $/;

# Считываем содержимое всего файла в переменную $_
$_=<FIN>;

# Разбиваем переменную $_ на поля по пробельным символам
# и записываем поля в список @InputData
my @InputData=split;

# Теперь в элементах списка $InputData[0] и $InputData[1]
# записаны два входных числа. Запишем их сумму в переменную $Answer
my $Answer=$InputData[0]+$InputData[1];

# Выведем результат в файл
print FOUT $Answer;

# Закроем файлы FIN и FOUT
close(FIN);
close(FOUT);

php

<?php
# Считываем весь файл при помощи функции file_get_contents,
# удаляем начальные и конечные пробелы при помощи функции trim
# результат разбиваем на поля функцией split по шаблону /\s+/,
# задающему последовательность пробельных символов в качестве разделителя
# и записываем результат в массив InputData
$InputData=preg_split('/\s+/', trim(file_get_contents('sum.in')));

# Теперь в элементах массива $InputData[0] и $InputData[1]
# записаны два входных числа.
# Запишем их сумму в переменную $Answer
$Answer=$InputData[0]+$InputData[1];

# Объявляем файл FOUT для вывода данных
$FOUT=fopen("sum.out","w");

# Выведем результат в файл FOUT 
fputs($FOUT,$Answer);

# Закроем файл FOUT
fclose($FOUT);

?>

python

#!/usr/bin/python

# Объявляем файлы FIN и FOUT для ввода-вывода данных
FIN  = open("sum.in",  "r")
FOUT = open("sum.out", "w")

# Считываем весь файл при помощи метода read(),
# результат разбиваем на поля по пробельным символам методом split()
# и записываем в список InputData
InputData = FIN.read().split()

# Теперь в элементах списка InputData[0] и InputData[1]
# записаны два входных числа в виде строк.
# Преобразуем их к типу int и запишем их сумму в переменную Answer
Answer = int(InputData[0]) + int(InputData[1])

# Выведем результат в файл
print >> FOUT, Answer

# Закроем файлы FIN и FOUT
FIN.close()
FOUT.close()


ruby

#!/usr/bin/ruby

# Объявляем файлы FIN и  FOUT для ввода-вывода данных
FIN  = open("sum.in",  "r")
FOUT = open("sum.out", "w")

# Считываем весь входной файл при помощи метода read(),
# результат разбиваем на поля по пробельным символам методом split()
# и записываем в список InputData
InputData = FIN.read().split()

# Теперь в элементах списка InputData[0] и InputData[1]
# записаны два входных числа в виде строк.
# Преобразуем их к целочисленному типу и запишем их сумму в переменную Answer
A=InputData[0].to_i
B=InputData[1].to_i
Answer=A+B

# Выведем результат в файл FOUT 
FOUT.puts(Answer)

# Закроем файлы FIN и FOUT
FIN.close()
FOUT.close()