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


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останній тестовий випадок.
Leaky Nun

@LeakyNun Добре тоді, я думаю, я пропустив їх під час їх підрахунку . Це виправлено.
Р. Кап

Яке максимальне значення введення?
Ерік Аутгольфер

Відповіді:


34

Пітон, 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

Хороша робота. Пальці вгору. :)
Р. Кап

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 так, що ти кажеш ... Magic
Pureferret


9

Математика, 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)

Цікавий факт: ця реалізація настільки golfy, це такі ж довжини, вбудовані для обчислення одного трикутного числа, PolygonalNumber.



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яке друкує кінцевий результат.


Я міг би скласти присягу, що я прочитав щось у документах про ціле ділення ...
Conor O'Brien

7

R, 40 35 байт

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

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

EDIT : У цій версії 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/}~.

На основі видатного рішення python xnor.

Пояснення:

{_:)+:*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

Матлаб, 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;}

Java 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->працювати? Ось ідеон для поточної справи.
Kevin Cruijssen

1
Вибачте за дуже пізню відповідь! Вам потрібно завищити функцію, тому вам потрібно змінити, MathOperation.operationщоб взяти лише один int, повернути a 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

Не потрібно називати це - анонімні функції нормально згідно з умовами сайту
Conor O'Brien

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.

Потім Лабіринт намагається виконати /ще раз, що припиняє програму через ділення на нуль.




1

Pyth, 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

C #, 19 байт

(n,m)=>m*n*~m*~n/4;

Анонімна функція, заснована на відповіді @ xnor.


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, це технічно функція зі змінними аргументами, які можна викликати, загортаючи її у операторну функцію або завантажуючи її з вихідного коду за допомогою "loadstring"


1
Я бачу, що у вас там дуже багато коду тільки для вводу / виводу. Можливо, було б коротше просто зробити функцію, яка приймає два числа і повертає відповідь, і видаляє весь цей непотрібний код вводу-виводу?
Звей

@Zwei Я забув, що функції можуть приймати дані за параметрами. Дякуємо, що вказали на це.
brianush1

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

У Луї ключове слово "функція" необхідне для оголошення функції. Якщо не вказано ім’я (наприклад: "функція f ()"), це анонімна функція. (напр .: "функція ()"). Тому для роботи коду потрібна «функція».
brianush1

О, я забув, що Луа працює так. Моє ліжко!
Zwei


1

Мозг-Флак , 84 80 байт

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

Спробуйте в Інтернеті!

Напевно, дуже неоптимальне, особливо через повторне використання коду щодо чисел трикутника, але принаймні у нас є рішення Brain-Flak, яке працює.

На жаль, це, здається, не вдається, нескінченно 0 0зациклюючись на тестовій шафі, але всі інші працюють чудово.




Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.