Сколько прямоугольников в сетке?


29

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

Теперь для тех из вас, кто хочет решить эту проблему проблему, вот оно.


Ну, у нас пока нет такой задачи, так что мы здесь.

Рассмотрим эту 3 x 3сетку прямоугольников:

пример

Сколько есть прямоугольников? Что ж, считая визуально, мы можем видеть, что на самом деле есть 36прямоугольники, включая всю плоскость, которые все показаны в анимированном GIF ниже:

Прямоугольники в примере

Задание

Подсчет прямоугольников, как показано выше, является задачей. Другими словами, учитывая, что 2 целых числа больше или равны 0, mи n, где mпредставляет ширину и nвысоту, выведите общее количество прямоугольников в этомm x n сетке прямоугольников.

правила

  • Использование любых встроенных программ, которые непосредственно решают эту проблему, явно запрещено.

  • Эта задача не в том, чтобы найти самый короткий ответ, а в том, чтобы найти самый короткий ответ на каждом языке. Поэтому ответ не будет принят.

  • Стандартные лазейки запрещены.

Тестовые случаи

Представлено в формате Array of Integers Input -> Integer Output:

[0,0] -> 0
[1,1] -> 1
[3,3] -> 36 (Visualized above)
[4,4] -> 100
[6,7] -> 588

Ссылки

Помните, это , поэтому выигрывает самый короткий код!


Я рассчитал 588на последний тест-кейс.
Утренняя монахиня

@ LeakyNun Ну тогда, я думаю, я пропустил некоторые, подсчитывая их. Это фиксированный.
Р. Кап

Каково максимальное значение входа?
Эрик Outgolfer

Ответы:


34

Python, 22 байта

lambda m,n:m*~m*n*~n/4

Формула m*n*(m+1)*(n+1)/4сокращается с использованием битового дополнения ~m=-(m+1), выраженного (m+1)*(n+1)как ~m*~n.

Почему количество прямоугольников m*n*(m+1)*(n+1)/4? Каждый прямоугольник определяется выбором двух горизонтальных линий (сверху и снизу) и двух вертикальных линий (слева и справа). Есть m+1горизонтальные линии, из которых мы выбираем подмножество двух разных. Так что количество вариантов есть choose(m+1,2), которое есть m*(m+1)/2. Умножение на n*(n+1)/2выбор для вертикальных линий дает результат.


+1 трюк блестящий.
Дэвид Люнг Мэдисон Стеллар

11

Желе , 4 байта

RS€P

Попробуйте онлайн!

Кроме того, также 4 байта

pP€S

Попробуйте онлайн!


Отличная работа. Недурно. :)
Р. Кап

24
Хотите объяснить?
Pureferret

Есть также בHPи, ‘c2Pвозможно, другие 4-байтовые альтернативы.
миль

1
@Pureferret При этом используется формула из OEIS об этом являющемся продукте nthи mthтреугольного числа. Rпреобразует каждое число в 1 на основе индекса на: [1, 2, ..., n]. Sэто сумма и означает «каждый» , поэтому каждый список суммируются, давая список как: [nth triangle number, mth triangle number]. Затем Pберется произведение этого списка, которое дает желаемый результат.
FryAmTheEggman

1
@FryAmTheEggman, так что вы говорите .... Магия
Pureferret

9

Javascript (ES6), 17 байт

m=>n=>m*n*~m*~n/4

Вилка этого ответа .

f=m=>n=>m*n*~m*~n/4
alert(f(prompt())(prompt()))


Я не уверен, хорошо ли карри в языках, которые не делают этого по умолчанию?
Джон Дворак


9

Mathematica, 15 байт

##(1##+##+1)/4&

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

объяснение

Реализация в основном представляет собой очень сложную форму произведения двух треугольных чисел. Возможно, стоит прочитать раздел «Последовательность аргументов» в этом посте , но я постараюсь обобщить суть здесь.

##расширяется до последовательности всех аргументов. Это похоже на сплаттинг на других языках. Например, если аргументы есть 3и 4, то {1, 2, ##, 5}даст вам {1, 2, 3, 4, 5}. Но это не только работает в списках, но в любом выражении, например f[1, 2, ##, 5], также будетf[1, 2, 3, 4, 5] .

Это становится интересным, когда вы объединяетесь ##с операторами. Все операторы в Mathematica - это просто короткие f[...]выражения для некоторого подобного выражения (возможно, вложенного). Например, a+bэто Plus[a, b]и есть на a-bсамом деле Plus[a, Times[-1, b]]. Теперь, когда вы объединяете ##с операторами, Mathematica сначала расширяет операторы, обрабатывая их ##как один операнд, и расширяет их только в конце. Вставляя ##в правильные места, мы можем использовать его как для умножения, так и для добавления операндов.

Давайте сделаем это для кода выше:

##(1##+##+1)/4

Развернув его до полной формы, мы получим следующее:

Times[##, Plus[Times[1, ##], ##, 1], Rational[1/4]]

Давайте вставим аргументы функции aи b:

Times[a, b, Plus[Times[1, a, b], a, b, 1], Rational[1/4]]

А теперь мы конвертируем его обратно в стандартную математическую запись:

a * b * (a * b + a + b + 1) / 4

Небольшая перестановка показывает, что это произведение треугольных чисел:

a * b * (a + 1) * (b + 1) / 4
(a * (a + 1) / 2) * (b * (b + 1) / 2)
T(a) * T(b)

Забавный факт: эта реализация настолько игривая, она имеет ту же длину, что и встроенная для вычисления одного треугольного числа PolygonalNumber.


8

C, 25 байтов

#define r(x,y)x*y*~x*~y/4

Пуристическая версия (27):

r(x,y){return x*y*~x*~y/4;}

Версия ISO-er (35):

#define r(x,y)((x)*(y)*~(x)*~(y)/4)

Какую версию вы считаете лучшей?
Эрик Outgolfer

8

Медуза , 16 байт

p|%/**+1
  4  Ei

Формат ввода есть [x y], вывод - это просто результат.

Попробуйте онлайн!

Альтернативное решение с тем же количеством байтов:

pm%/*[*i
  4  +1

объяснение

Время дать медузу представление, которого она заслуживает! :)

Медуза - это язык Згарба , основанный на его 2D-синтаксисе . Семантика в значительной степени вдохновлена ​​J, но синтаксис - произведение искусства. Все функции являются отдельными символами и расположены на сетке. Функции берут свои аргументы из следующего токена к югу и востоку от них и возвращают результат к северу и западу. Это позволит вам создать интересную сеть вызовов функций, где вы будете повторно использовать значения, передавая их в несколько функций из разных направлений.

Если мы игнорируем тот факт, что некоторые из токенов в вышеприведенной программе являются специальными операторами (высокоуровневые функции), вышеприведенная программа будет написана примерно так на нормальном языке:

p(|( /*(i*(i+1)) % 4 ))

Давайте рассмотрим код снизу вверх. Ввод получает от i, который, следовательно, оценивается в [x y].

+На вершине этого получает этот вход вместе с буквальным 1и , следовательно , увеличивает оба элемента , чтобы дать [(x+1) (y+1)](большинство операций нанизаны автоматически над списками).

Другое значение iотправляется влево, но Eраскол является восточным аргументом север и запад. Это означает, что входные данные на *самом деле являются фактическими, [x y]и [(x+1) (y+1)]поэтому это вычисляется [x*(x+1) y*(y+1)].

Следующий *шаг на самом деле изменяется предшествующим, /что превращает его в операцию сгиба. Складывание *пары просто умножает это, так что мы получаем x*(x+1)*y*(y+1).

Теперь %это просто деление, поэтому оно вычисляет x*(x+1)*y*(y+1)/4. К сожалению, это приводит к плавающему значению, поэтому нам нужно округлить его с одинарным |. Наконец, передается это значение, pкоторое печатает конечный результат.


Я мог бы поклясться, что прочитал кое-что в документах о целочисленном делении ...
Конор О'Брайен

7

R, 40 35 байт

Ну что ж, пора прыгать в глубокий конец! Вот мой код R , вдохновленный ответом @xnor:

a=scan();(n=a[1])*(m=a[2])*(n+1)*(m+1)/4 

РЕДАКТИРОВАТЬ : В этой версии R будет запрашивать ввод дважды.

(n=scan())*(m=scan())*(n+1)*(m+1)/4

cat(prod(choose(scan()+1,2)))составляет 29 байт.
Джузеппе

6

CJam, 12 10 байт

2 байта сохранены благодаря Мартину.

{_:)+:*4/}

Попробуйте онлайн!

Это блок, который берет список из 2 элементов из стека и оставляет решение в стеке. Используется полная программа для тестирования: riari+{_:)+:*4/}~.

Основано на выдающемся решении xnor Python.

Объяснение:

{_:)+:*4/}
{        } -- Define a block
 _:)       -- Duplicate list, increment all values in new list
    +      -- Join the two lists
     :*    -- Fold multiply over all 4 elements
       4/  -- Divide by 4

2
Я думаю, что это работает для 10, если вы делаете ввод списка из двух элементов? {_:~+:*4/}
Мартин Эндер

На самом деле, ~в CJam вообще нет необходимости использовать . Просто используйте ).
Мартин Эндер

5

Matlab, 23 19 байт

@(x)prod([x/2,x+1])

Реализация формулы m*n*(m+1)*(n+1)/4
использования:ans([m,n])


4

MATL , 6 байтов

tQ*2/p

Ввод является массивом формы [m,n].

Попробуйте онлайн!

объяснение

Прямые вычисления по формуле m*(m+1)*n*(n+1)/4.

t     % Input array [m,n] implicitly. Duplicate
Q     % Add 1 to each entry of the copy: gives [m+1,n+1]
*     % Multiply element-wise: gives [m*(m+1),n*(n+1)]
2/    % Divide each entry by 2: [m*(m+1)/2,n*(n+1)/2]
p     % Product of the two entries: m*(m+1)*n*(n+1)/4. Display implicitly


4

Java 7, 39 38 байт

int c(int a,int b){return~a*a*b*~b/4;}

Ява 8, 26 25 19 18 17 байт

a->b->a*~a*b*~b/4

Основано на превосходном ответе @xnor . Несколько байтов сохранено благодаря @DavidConrad . Попробуй это здесь.

Тестовый код (Java 7):

Попробуй это здесь.

class M{
  static int c(int a,int b){return~a*a*b*~b/4;}

  public static void main(String[] a){
    System.out.println(c(0, 0));
    System.out.println(c(1, 1));
    System.out.println(c(3, 3));
    System.out.println(c(4, 4));
    System.out.println(c(6, 7));
  }
}

Выход:

0
1
36
100
588

1
Вам это не нужно returnи a->b->на один байт короче (a,b)->.
Дэвид Конрад

2
Я не думаю, что вам также нужна точка с запятой, поскольку, если бы вы передавали лямбду в метод, который принимал Function<Integer, Function<Integer, Integer>>в качестве параметра, за ней не следовала бы точка с запятой.
Дэвид Конрад

2
Я согласен с @DavidConrad: я не считаю окончание ;на одном утверждении J8 лямбда-выражений.
CAD97

@DavidConrad Извините за очень позднее редактирование, но я только сейчас заметил, что прочитал ваш комментарий, чтобы удалить return .. Кроме того, я почти никогда не программирую на Java 8 (отсюда и все мои ответы на Java 7), но как мне начать a->b->работать? Вот идеон для текущего дела.
Кевин Круйссен

1
Извините за очень поздний ответ! Вам нужно , чтобы снискать функцию, так что вам нужно изменить , MathOperation.operationчтобы принимать только один int, то возвращается Function<Integer, Integer>, и когда вы звоните, вы сначала пройти только первый параметр, aи затем вызвать .apply(b)на Function. Вам также необходимо импортировать java.util.function.Function. Вот идеон с изменениями.
Дэвид Конрад

3

Рубин, 22 байта

Кража уловки @ xnor и создание лямбды

r=->(m,n){m*n*~m*~n/4}

Пример вызова:

r[6,7]     # => 588

Или как процесс, также 22 байта:

proc{|m,n|m*n*~m*~n/4}

Который мы могли бы тогда назвать:

proc{|m,n|m*n*~m*~n/4}.call(6,7)     # => 588

Вам не нужно называть это имя - анонимные функции в соответствии с конвенцией сайта в порядке
Конор О'Брайен

3

Лабиринт , 13 11 байт

*?;*_4/!
):

Попробуйте онлайн!

объяснение

Это также вычисляет произведение треугольных чисел, как и большинство ответов. Ведущий блок 2x2 представляет собой небольшой цикл:

*?
):

На первой итерации *ничего не делает, так что реальный порядок циклов такой:

?   Read integer N from STDIN or 0 at EOF and push onto stack. If 0, exit the loop.
:   Duplicate N.
)   Increment.
*   Multiply to get N*(N+1).

Оставшийся код просто линейный:

;   Discard the zero that terminated the loop.
*   Multiply the other two values.
_4  Push a 4.
/   Divide.
!   Print.

Затем Лабиринт пытается выполнить /снова, что завершает программу из-за деления на ноль.



2

05AB1E, 4 байта

€LOP

объяснение

Использует формулу, описанную в A096948

      # Implicit input, ex: [7,6]
€L    # Enumerate each, [[1,2,3,4,5,6,7],[1,2,3,4,5,6]]
  O   # Sum, [28,21]
   P  # Product, 588
      # Implicit display

Принимает ввод как [n, m] .

Попробуйте онлайн


1

Пиф, 8 6 байтов

Два байта сохранены благодаря @DenkerAffe.

*FmsSd

Ввод ожидается в виде списка [m,n]. Попробуйте это здесь .

Объяснение:

          Implicit assignment of Q to eval(input).
*         Multiplication.
 F        Splat the following sequence onto the arguments of the previous function.
  m       Map the following function of d over Q (Q is implicitly added to the end).
   s      Reduce the following list with addition, initial value of 0.
    Sd    Return range(1,d+1).

1
Вы можете использовать Fвместо .*и удалить, Qпоскольку он добавлен неявно.
Денкер

Я знал об этом, Fно я не мог понять, как его использовать, и решил, что мне нужно использовать .*вместо этого ... Спасибо!
Rhyzomatic


1

Луа, 74 63 байта

x,y=...n=0 for i=1,y do for j=i,i*x,i do n=n+j end end print(n)

Функция принимает входные данные в качестве числовых параметров.

Из-за того, как реализован Lua, технически это функция с переменными аргументами, которую можно вызвать, обернув ее в оператор «function» или загрузив ее из исходного кода с помощью «loadstring»


1
Я вижу, что у вас достаточно кода для ввода-вывода. Возможно, было бы короче просто сделать функцию, которая берет два числа и возвращает ответ, и удаляет весь этот ненужный код ввода / вывода?
Цвей

@ Zwei Я забыл, что функциям разрешено принимать данные по параметрам. Спасибо что подметил это.
brianush1

Функция может быть названа как «f» вместо целого имени «function», чтобы сохранить еще 7 байтов
Zwei

В Lua ключевое слово «function» требуется для объявления функции. Если имя не указано (например, «function f ()»), это анонимная функция. (например: «функция ()»). Поэтому для работы кода требуется «функция».
brianush1

О, я забыл, что Луа работает так. Виноват!
Цвей


1

Brain-Flak , 84 80 байтов

({}<>)({({})<({}[()])>}{})<>({({})<({}[()])>}{}[()]){<>(({}))<>({}[()])}<>({{}})

Попробуйте онлайн!

Вероятно, очень неоптимальный, особенно из-за повторного использования кода в отношении номеров треугольников, но по крайней мере у нас есть решение Brain-Flak, которое работает.

К сожалению, кажется, что это невозможно, бесконечно зацикливаясь на 0 0тестовом примере, но все остальные работают нормально.




Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.