Порахуйте прямокутники по діагональній сітці


21

Як наступне завдання для цього завдання , ми хочемо тепер порахувати кількість прямокутників в сітці з r рядками та c стовпцями, де в кожній діагоналі квадрата в сітці є лінія, що перетинає. Зараз ми все ще рахуємо ті ж прямокутники, що і раніше, але цього разу ми повинні також включити прямокутники, нахилені на 45 градусів.

Ваша мета - створити функцію або програму, яка з урахуванням кількості рядків r та стовпців c виводить кількість прямокутників у діагональній сітці з розмірами ( r , c ).

Як демонстрація, це анімація, яка проходить через усі 37 прямокутників, утворених діагональною сіткою (2 х 3).

Приклад

Випробування

Each case is [rows, columns] = # of rectangles
[0, 0] = 0
[0, 1] = 0
[1, 0] = 0
[1, 1] = 1
[3, 2] = 37
[2, 3] = 37
[6, 8] = 2183
[7, 11] = 5257
[18, 12] = 40932
[42, 42] = 2889558
[51, 72] = 11708274

Правила

  • Це тому найкоротший код виграє.
  • Вбудовані, що вирішують це, заборонені.

7
Тільки Mathematica могла мати вбудований для цього XD
Conor O'Brien

3
Боже, це набагато складніше, ніж інші прямокутники .....
GamrCorps

5
Дивіться пов'язаний виклик projecteuler.net/problem=147
Маркус Ендрюс

1
Я думаю, вбудовані модулі повинні бути дозволені. Мені подобається бачити ці відповіді.
mbomb007

Відповіді:


8

Рубін, 58 байт

Це прямо реалізація алгоритму у звільненні відповіді на гелій Нуклеї .

g=->m,n{n>m ?g[n,m]:m*~m*n*~n/4+n*((2*m-n)*(4*n*n-1)-3)/6}

Я досліджував, чому ця формула працює, з обмеженим успіхом. Неважко підтвердити, що кількість прямокутних прямокутників дорівнює (m+1)*m/2 * (n+1)*n/2, кількість діагональних прямокутників трохи невловиміше.

Ніл підтвердив для m==nщо кількість похилих прямокутників в n*nквадраті , (4*n**4-n*n-3*n)/6і що , коли m>n вам потрібно додати додатковий (m-n)(n*(4*n*n-1)/3)(пов'язаний з OEIS A000447 ), хоча це не пояснює , де ці дві формули прийшли. Я знайшов частину відповіді.

Бо m==nформа всередині сітки - алмаз ацтеків .

Образ ацтекського алмаза від Wolfram Alpha

Кількість прямокутників в ацтекської алмазі є сума ряду великих прямокутників накладається , щоб зробити це (за четвертий алмаз, який знаходиться в 5x5сітці 2x8, 4x6, 6x4і 8x2) мінус число прямокутників пораховано двічі (число прямокутники в попередньому алмазному ацтеку).

Формула тут (TeX буде додано пізніше):

# superimposed rectangles, 2x(2n-2), 4*(2n-4), ...
f = lambda n: sum( (2*k)*(2*k+1)/2 * (2*n-2*k)*(2*n-2*k+1)/2 for k in range(1, n) )
aztec_rect = f(n) - f(n-1)

Згідно Wolfram Alpha, в замкнутій формі для fIS 1/30*(n-1)*n*(4*n**3+14*n**2+19*n+9)і закритої форми aztec_rectє, як виявив Ніл 1/6*n*(n-1)*(4*n**2+4*n+3) == 1/6*(4*n**4-n**2-3*n).

Я до сих пір зрозуміти , чому (m-n)(n*(4*n*n-1)/3)працює, хоча я підозрюю , що це тому , що одне визначення A000447 є binomial(2*n+1, 3). Я буду тримати вас в курсі.

Оновлення: У мене є підстави вважати, що функція кількості прямокутників у розширеному алмазному ацтеку m>nпов'язана з кількістю накладених 2k*2(n-k)прямокутників у мінус алмазу F(m-1,n-1). Більше результатів, коли я їх маю.

Оновлення: я спробував інший маршрут і закінчив іншу формулу для розширених алмазів ацтеків, яка в основному пояснюється, але має один термін, який я ще не розумію. Huzzah! : D

def f(m,n):
 if n > m:
     return f(n,m)
 if n == 0:
     return 0
 else:
     return(m-n+1)*(4*n**4-n*n-3*n)/6-f(m-1,n-1)+(m-n)*2+(m-n)*(n-2)-(m-n-1)*f(n-1,n-1)

Швидкий розбір цієї останньої формули:

  • (m-n+1)*(4*n**4-n*n-3*n)/6- кількість накладених ацтекських алмазів розміром nу структурі, як f(n,n) = (4*n**4-n*n-3*n)/6. f(7,3)має 5 накладених алмазів розміром ацтеків 3, тоді як f(3,3)має лише 1 алмаз.
  • -f(m-1,n-1) видаляє частину повторюваних прямокутників із середини накладених ромбів.
  • +(m-n)*2становить 2 додаткових 2матрицю з розмірністю (2n-1)прямокутників для кожного додаткового діаманта.
  • +(m-n)*(n-2)рахунки за додаткову nматрицю з розмірністю nквадрата для кожного додаткового діаманта.
  • -(m-n-1)*f(n-1,n-1)Це новий загадковий термін. Мабуть, я не рахував якихось зайвих квадратів у своєму підрахунку, але я не зрозумів, де вони знаходяться в розширеному діаманті.

Примітка: коли m==n, m-n-1 = -1маючи на увазі, що цей останній член додає квадрати до підрахунку. Я можу щось бракувати в моїй звичайній формулі. Повне розкриття, це було призначено лише для виправлення попереднього проекту цієї формули, який щойно спрацював. Ясна річ, мені все одно потрібно розібратися в тому, що відбувається, і, можливо, у моїй формулі є деякі помилки. Я буду тримати вас у курсі.

Рассел, Гері та Вайштайн, Ерік У. "Ацтек Алмаз". Від MathWorld - веб-ресурс Wolfram. http://mathworld.wolfram.com/AztecDiamond.html


Мені подобається, як ця відповідь має більше прибутків, ніж оригінальна відповідь, і +100 щедрість ...: P
HyperNeutrino

5

C, 71 64 байти

f(m,n){return n>m?f(n,m):m*~m*n*~n/4+n*((2*m-n)*(4*n*n-1)-3)/6;}

Спробуйте це на Ideone


2
Я хотів би знати, що тут відбувається, і як ти дійшов до цього рішення.
Йорданія

1
@ Джордан Поки я перевірив другу половину формули для m==n: кількість нахилених прямокутників у n*nквадраті дорівнює (4*n*n*n*n-n*n-3*n)/6. Послідовність дорівнює 0, 9, 51, 166, 410, 855, 1589, 2716, 4356, 6645, але вона не відображається в OEIS.
Ніл

1
Зараз я перевірив, що коли m>nпотрібно додати додаткову (m-n)(n*(4*n*n-1)/3)(останню частину формули, взятої з OEIS A000447). Перестановка та додавання дає формулу @ betseg.
Ніл

@Neil Як ти дійшов до цих формул?
Шерлок9

2
@ Sherlock9 Я вручну підрахував кількість нахилених прямокутників у перших 10 квадратах і подав послідовність у пошукову систему OEIS, яка не розпізнала послідовність, але знайшла формулу для неї, яка відповідає формулі ОП m==n. Потім я вручну обчислював кількість нахилених прямокутників у невеликих прямокутниках і помітив, що збільшуючи довший розмір, завжди додавали однакову кількість прямокутників для заданого коротшого розміру. Я вводив приріст в OEIS, який знайшов збіг на A000447.
Ніл

4

Пітон, 73 68 байт

x=lambda m,n:m*~m*n*~n/4+n*((2*m-n)*(4*n*n-1)-3)/6if m>n else x(n,m)

І хоча наступна версія має більший кількість рахунків (75), це було приємним вправою у пошуку місця для використання ~:

def f(r,c):
 if r<c:r,c=c,r
 x=(4*c**3-c)/3
 return r*c*~r*~c/4+x*r--~x*c/2

68 байт, якщо ви використовуєте лямбда:x=lambda m,n:m*~m*n*~n/4+n*((2*m-n)*(4*n*n-1)-3)/6if m>n else x(n,m)
GamrCorps

Ах, я чомусь припустив, що нам доведеться користуватися def. Спасибі! Оновлено.
Маркус Ендрюс

3

Опукла, 37 36 байт

__:)+×½½\~æ<{\}&:N\¦\-N¦¦N*(*3-N*6/+

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

Використовується алгоритм betseg, модифікований та оптимізований для мови на основі стека. Пояснення, коли я маю ще вільний час. Надіюсь, це можна скоротити, але наразі я не збираюся турбуватись.


2

Пакет, 82 байти

@if %2 gtr %1 %0 %2 %1
@cmd/cset/a%1*~%1*%2*~%2/4+((%1+%1-%2)*(%2*%2*4-1)-3)*%2/6
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.