Блог пользователя Nickolas

Автор Nickolas, 8 лет назад, По-русски

Во всех задачах, как и в примере, используется одинаковое определение глаголов для ввода-вывода данных:

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
  • Проголосовать: нравится
  • +56
  • Проголосовать: не нравится

»
8 лет назад, # |
  Проголосовать: нравится +79 Проголосовать: не нравится

Now perl seems to be very readable language :)

»
8 лет назад, # |
  Проголосовать: нравится +20 Проголосовать: не нравится

а я-то думал паскаль не очень удобный...

»
8 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится

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

in =. ('\r';' ') rxrplc (read-.LF)
print +/ ". in
»
8 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

А кто-нибудь нашел нормальный туториал, с помощью которого можно дойти дальше второй задачи?

Даже не смог нагуглить как делать ввод с файла. Не говоря уже как разбить это в массив.

  • »
    »
    8 лет назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится

    Для меня ввод из файла и вывод на печать были самыми сложными частями подготовки контеста. Именно поэтому в анонсе контеста вместе с языком и ссылками дан пример A+B, в котором показаны ввод данных, разбиение введенного на элементы и вывод результата :-)