Во всех задачах, как и в примере, используется одинаковое определение глаголов для ввода-вывода данных:
print =: 1!:2&2
read =: 1!:1[3
Кроме того, скрипты завершаются командой exit ''.
640A - Ленивый блинорез
Как обычно, первая задача проверяет способность участника выполнять базовые арифметические действия языка. Даже в таком необычном языке, как J, арифметика выглядит довольно стандартно, за исключением того, что в отсутствие скобок операции выполняются справа налево, без приоритетов, и деление обозначается символом %. Глагол ". преобразует строку в число или массив чисел.
n =. ". (read-.LF)-.CR
print 1 + (n * (n + 1)) % 2
640B - Времена года
Эта задача должна была намекнуть участникам на то, что в J существуют обычные императивные структуры для циклов и условного выполнения действий. В данном случае удобно использовать конструкцию select. case. do..
month =. (read-.LF)-.CR
season =: monad define
select. y
case. 'December';'January';'February' do. 'winter'
case. 'March';'April';'May' do. 'spring'
case. 'June';'July';'August' do. 'summer'
case. 'September';'October';'November' do. 'autumn'
end.
)
print season month
640C - Сумма массива
Программа A+B, данная в примере, на самом деле вычисляет сумму произвольного количества чисел, но только если все из них даны в одной строке. J читает весь входной файл целиком, поэтому если числа записаны в разных строках, прочитанные данные будут представлять собой одну строку с числами, разделеными символами CR (#13) и LF (#10). Для вычисления их суммы нужно преобразовать прочитанную строку в массив строк, содержащих по одному числу каждая. Это удобно сделать следующим образом: при чтении убрать символы CR, а затем использовать глагол ;._2, чтобы разбить строку на части, содержащиеся между символам LF (последний символ строки).
inraw =. read -. CR
NB. we know that last character will be LF, so use _2 to use last character as delimiter and exclude it from intervals
print +/ ". ;._2 inraw
640D - Максимальная разность
Изящество языка J заключается в том, что все действия производятся не над скалярами, а над массивами. Так, в этой задаче можно представить искомую величину как разультат следующих действий над массивами: получить массив a1 как (исходный массив без первого элемента) }., массив a2 как (исходный массив без последнего элемента) }:, вычесть эти два массива друг из друга (т.е. создать массив разностей соответствующих элементов) и найти максимум абсолютных значений этого массива.
arr =. ". (read-.LF)-.CR
diffs =. (}. arr) - (}: arr)
print >./ | diffs
640E - Проверка делимости
Если такое число существует, то оно равно наименьшему общему кратному всех чисел массива (потому что оно должно делиться не только на остальные числа, но и на себя само). Кроме того, оно будет наибольшим из чисел массива. Стандартные глаголы [*.](http://code.jsoftware.com/wiki/Vocabulary/stardot#dyadic) и >. позволяют найти НОК и максимум массива, остается их сравнить. Результат сравнения как раз и будет 1, если эти величины равны, и 0 в противном случае.
arr =. ". (read-.LF)-.CR
print (*. / arr) = (>. / arr)
640F - Простые числа на интервале
Глагол p: позволяет вернуть простое число по его порядковому номеру. Обратный глагол p:^:_1 возвращает количество простых чисел меньших аргумента.
in =. (read -.LF) -.CR
NB. split on space and convert to integers
ab =. ". ;._1 ' ',in
NB. first element is A, second is B - need to increment B to get upper bound inclusive
abinc =. ab + (0 1)
NB. apply inverse of primes
nprimes =. p:^:_1 abinc
NB. subtract first element (head) from second (tail)
print ({: nprimes) - ({. nprimes)
640G - Венгерская нотация
В этой задаче надо было использовать какую-нибудь условную конструкцию, чтобы определить, есть ли в значении переменной десятичная точка.
inraw =. read -. CR
a =. <;._2 inraw
name =. > {. a
content =. > {: a
capName =. (toupper {. name),(}. name)
typeChar =: monad define
if. (y +./@:E.~ '.') do. 'f' elseif. do. 'i' end.
)
print (typeChar content),capName
640H - Поворот матрицы
Эта задача демонстрирует всю мощь языка J в обработке матриц — решение на J короче, чем на C++ :-) Чтобы повернуть матрицу на 90 градусов по часовой стрелке, ее нужно транспонировать (глагол |:), а затем развернуть отдельно каждую строку (глагол |."1).
inraw =. read -. CR
NB. first split on LF, then convert to numbers (splitting on space)
m =. ". ;._2 inraw
print |."1 |: m
Now perl seems to be very readable language :)
а я-то думал паскаль не очень удобный...
In C, I couldn't figure out how to take multiline input, so I used regexp to replace all newlines with spaces and then split the string to form a array. :D
А кто-нибудь нашел нормальный туториал, с помощью которого можно дойти дальше второй задачи?
Даже не смог нагуглить как делать ввод с файла. Не говоря уже как разбить это в массив.
Для меня ввод из файла и вывод на печать были самыми сложными частями подготовки контеста. Именно поэтому в анонсе контеста вместе с языком и ссылками дан пример A+B, в котором показаны ввод данных, разбиение введенного на элементы и вывод результата :-)