Полезные фишки, которые серьёзно упрощают работу под линуксом, и в частности под IOI-окружением, отмечены красными восклицательными знаками (!).

Работаем в терминале

Шпаргалка по командам (bash):

(!) Сильно упрощает работу с терминалом включение цветного режима, который подсвечивает приглашение bash, а также вывод разных команд (например, папки в выводе ls будут окрашены в синий цвет). Для этого надо открыть файл ~/.bashrc, раскомментировать в нём строку #force_color_prompt=yes (удалить решётку из начала) и перезапустить терминал.

(!!) В баше есть автодополнение путей, которое очень ускоряет набор команд. Во время набора пути (или просто имени файла) можно нажать один или два раза кнопку tab. Например, пусть в текущей директории есть три файла: main_stup.cpp, main_opt.cpp и gen.cpp. Тогда можно вывести содержимое файла main_opt.cpp следующей последовательностью нажатий:

~/dir$ cat m<TAB> # в этот момент баш понимает, что дальше будет точно main_, и дополняет
~/dir$ cat main_<TAB><TAB> # баш не знает, хотим ли мы stup или opt, поэтому он выводит оба варианта
main_opt.cpp   main_stup.cpp  
~/dir$ cat main_o<TAB>
~/dir$ cat main_opt.cpp

(!) В путях можно пользоваться плейсхолдерами (звёздочками и вопросиками). Например, cp main* dir/ в предыдущем примере скопирует все файлы, начинающиеся на main, в папку dir/

Компилируем код

g++ main.cpp -o main [-O2] [-g] [-fsanitize=address] — скомпилировать исходник main.cpp на C++ в исполняемый файл main

Ключ -O2 включает режим оптимизации, с таким ключом ваши решения компилируется в тестирующей системе.

Ключ -g добавляет в исполняемый файл отладочную информацию, необходимо для последующей отладки с помощью gdb

(!!) Ключ -fsanitize=address добавляет вспомогательный код, который отлавливает ошибки неправильного обращения к памяти (в частности, выходы за границы массива, использование непроинициализированных переменных и прочее). Этот ключ очень замедляет исполнение, но позволяет убедиться, что у вас нет проезда по памяти

fpc main.pas -omain [-O2] [-g] — скомпилировать исходник main.cpp на C++ в исполняемый файл main

Смысл ключей тот же самый, что и в g++.

Запускаем код

Запустить решение: ./main [<IN] [>OUT], с помощью угловых скобок можно перенаправить из файла IN или в файл OUT

Запустить скрипт на Питоне: python main.py [<IN] [>OUT]

(!) Убрать ограничение на размер стека (влияет на всю сессию bash): ulimit -s unlimited

Измерить время работы решения: time ./main <in.txt >out.txt

Пишем стресс чтобы не испытывать стресс!

while true
do
	# генерируем тест
	python gen.py >test.in
	# или (если вы пишете на плюсах)
	./gen >test.in

	# конструкция  "|| break" выкидывает из цикла если код выхода main ненулевой
	./main <test.in >test.out || break
	# пусть naive это тупое решение	
	./naive <test.in >test.out || break

	# если ответ не единственный, то придётся написать чекер и сделать так, чтобы 
	# он выходил с кодом возврата 0, если ОК, и с кодом возврата не 0, если не ОК
	# иначе подходит обыкновенный diff
	diff output.txt answer.txt || break
done
        

Запуск на всех тестах в папке, цикл for

for t in 01 02 03 50 99
do
	# это в предположении, что входные данные называются 01, 02 и так далее, ответы попадут в 01.r, ...
	./main <$t >$t.r 
done
		

(!) Вместо явного перечисления тестов можно пользоваться шаблонами. Например: input_*.txt это все файлы, где вместо звёздочки стоит 0 или больше символов, ?? это все файлы, состоящие из ровно двух символов. Это может быть полезно, чтобы, например, удалить все файлы, обладающие каким-то расширением: rm *.r.

Gdb, базовые команды

# Компилируем с ключом -g.
~/dir$ g++ main.cpp -o main -g
~/dir$ gdb main 
# Вывалится большое приглашение. Можно вводить команды gdb.
# r означает запустить программу, можно указать произвольные аргументы командной
# строки, например, перенаправить ввод откуда-нибудь.
(gdb) r <test.in
# Предположим, программа где-то упала.
# bt от слова backtrace - показать стек исполнения.
(gdb) bt
# Если мы слишком глубоко по стеку (например в глубинах STL-ной реализации вектора), 
# можно перемещаться по стеку командами up и down.
(gdb) up
# p от слова print - напечатать значение переменной
(gdb) p arr[0]
(gdb) p x
# Чтобы поставить breakpoint, надо написать b [номер строки] или b [название функции].
(gdb) b main
# Чтобы удалить breakpoint, надо написать clear [номер строки] или clear [название функции].
# Запускаем программу заново.
(gdb) r <test.in
# Step out (без захода в функцию) делается с помощью команды n, step in с помощью команды s.
(gdb) n
(gdb) s
# Выйти из GDB - нажать ctrl-D.
(gdb) <ctrl>-D