Rectángulos en rectángulos
Este código de golf desafío le dará dos números enteros positivos ny kcomo entradas y tienen que contar el número de rectángulos con coordenadas enteras que se pueden extraer con vértices que tocan los cuatro lados de la \$n \times k\$ rectángulo $$ \{(x,y) : 0 \leq x \leq n, 0 \leq y \leq k\}. $$ Es decir, debería haber:
- al menos un vértice con una \$x\$-coordinada de \$0\$,
- al menos un vértice con una \$x\$-coordinada de \$n\$,
- al menos un vértice con una \$y\$-coordinada de \$0\$y
- al menos un vértice con una \$y\$-coordinada de \$k\$.
Ejemplo
Hay \$a(5,7) = 5\$rectángulos con coordenadas enteras que tocan los cuatro lados de un \$5 \times 7\$ rectángulo:
Mesa
El triángulo inferior de la tabla (simétrica) de \$a(n,k)\$para \$n,k \leq 12\$ es
n\k| 1 2 3 4 5 6 7 8 9 10 11 12
---+----------------------------------------------
1 | 1 . . . . . . . . . . .
2 | 1 2 . . . . . . . . . .
3 | 1 1 5 . . . . . . . . .
4 | 1 1 1 6 . . . . . . . .
5 | 1 1 1 3 9 . . . . . . .
6 | 1 1 1 1 1 10 . . . . . .
7 | 1 1 1 1 5 1 13 . . . . .
8 | 1 1 1 1 1 1 5 14 . . . .
9 | 1 1 1 1 1 5 1 1 17 . . .
10 | 1 1 1 1 1 3 1 3 1 18 . .
11 | 1 1 1 1 1 1 5 1 5 5 21 .
12 | 1 1 1 1 1 1 1 1 5 1 1 22
Este es un desafío de código de golf , por lo que gana el código más corto.
Respuestas
05AB1E , 10 8 bytes
LDI-*`¢O
¡Pruébelo en línea!
Comentó :
# implicit input: [n, k]
L # for both values take the [1..x] range
# [[1,...,n], [1,...,k]]
D # duplicate this list
I # push the input [n,k]
- # subtract this from the ranges
# [[1-n,...,n-n], [1-k,...,k-k]]
# =[[-n+1,...,0], [-k+1,...,0]]
* # multiply with the ranges
# [[1*(-n+1),...,n*0], [1*(-k+1),...,k*0]]
` # push all lists of this list on the stack
¢ # count the occurences of each value of one list in the other
O # sum those counts
Python 2 , 66 59 bytes
lambda n,k:sum(a%n*(n-a%n)==a/n*(k-a/n)for a in range(n*k))
¡Pruébelo en línea!
Cada posible rectángulo dentro de \$n \times k\$-rectangle se puede especificar con dos enteros, \$0 \le a \lt n\$y \$0 \le b \lt k\$:
Para verificar un rectángulo dado \$a\$y \$b\$, basta con comprobar si un ángulo es recto. Para hacer esto, tomo el producto escalar de \$\binom{b}{0}-\binom{0}{a}=\binom{-b}{a}\$y \$\binom{k-b}{n}-\binom{0}{a}=\binom{k-b}{n-a}\$para comprobar si el ángulo en \$\binom{0}{a}\$ es un ángulo recto:
$$ \langle \left( \begin{matrix} -b \\ a \\ \end{matrix}\right), \left(\begin{matrix} k-b \\ n-a \\ \end{matrix} \right) \rangle = 0 \\\Leftrightarrow a\cdot(n-a)-b\cdot(k-b)=0 \\\Leftrightarrow a\cdot(n-a)=b\cdot(k-b) $$
C (gcc) , 63 61 bytes
Guardado 2 gracias a techocat !!!
s;a;f(n,k){for(s=a=n*k;a--;)s-=a%n*(n-a%n)!=a/n*(k-a/n);a=s;}
¡Pruébelo en línea!
Puerto de la respuesta de Python de ovs .
Scala , 65 64 60 51 bytes
n=>k=>0 to n*k-1 count(a=>a%n*(n-a%n)==a/n*(k-a/n))
¡Pruébelo en línea!
- -1 gracias al usuario !
- -4 gracias a ovs !
- -9 gracias a Kjetil !
Carbón , 21 bytes
NθNηIΣEθ№Eη×λ⁻ηλ×ι⁻θι
¡Pruébelo en línea! El enlace corresponde a la versión detallada del código. Explicación: Calcula \$ x(n-x) \$para \$ 0 \le x < n \$y \$ y(n-y) \$para \$ 0 \le y < k \$y cuenta el número de veces que aparece un número entero en ambas listas, que corresponde al paralelogramo con coordenadas \$ (x, 0), (0, y), (n - x, 0), (0, k - y) \$ tener ángulos de 90 grados:
NθNη
Entrada \$ n \$y \$ k \$.
IΣ
Genere la suma total de todas las coincidencias encontradas.
Eη×λ⁻ηλ
Calcular \$ y(n-y) \$para \$ 0 \le y < k \$.
Eθ№...×ι⁻θι
Calcular \$ x(n-x) \$para \$ 0 \le x < n \$ y cuente cuántas veces aparece cada número entero en la otra lista.
JavaScript (ES6), 63 58 56 bytes
Guardado 2 bytes gracias a @ovs
(n,y=x=0)=>g=k=>(x=x||++y*k--&&n)&&(y*k==--x*(n-x))+g(k)
¡Pruébelo en línea!
Retina , 45 bytes
\d+
*
L$w`(_+) (_+) $.`*$1=$.2*$' m`^(.*)=\1$
¡Pruébelo en línea! El enlace incluye un conjunto de pruebas. Toma entradas separadas por espacios. Explicación:
\d+
*
Convierta las entradas en unario.
L$w`(_+) (_+)
Coincide con todas las subcadenas que contienen _ _. Esto corresponde a todos los pares de \ $ 0 \ le x <n \ $ y \ $ 0 \ le y <k \ $ que están representados por las partes no coincidentes al principio y al final de la cadena $`y $'respectivamente mientras \ $ n - x \ $ y \ $ k - y \ $ están representados por $1y $2respectivamente.
$.`*$1=$.2*$'
Para cada par, enumere los productos (unarios) \ $ x (n - x) \ $ y \ $ y (k - y) \ $ .
m`^(.*)=\1$
Cuente el número de veces que son iguales.
Gelatina , 8 bytes
r1×ḶċⱮ/S
Un enlace monádico que acepta un par de números enteros que da lugar a la cuenta.
¡Pruébelo en línea! O vea la suite de pruebas .
¿Cómo?
r1×ḶċⱮ/S - Link [n,k]
r1 - ([n,k]) inclusive range to 1 = [[n,n-1,...,1],[k,k-1,...,1]]
Ḷ - lowered range ([n,k]) = [[0,1,...,n-1],[0,1,...,k-1]]
× - multiply = [[n×0,(n-1)×1,...,1×(n-1)],[k×0,(k-1)×1,...,1×(k-1)]]
/ - reduce by - i.e.: f(A=[n×0,(n-1)×1,...,1×(n-1)], B=[k×0,(k-1)×1,...,1×(k-1)])
Ɱ - map with - i.e.: [f(A,v) for v in B]
ċ - count occurrenes (of v in A)
S - sum
Haskell , 53 47 bytes
a#b=sum[1|x<-[1..a],y<-[1..b],x*(a-x)==y*(b-y)]
¡Pruébelo en línea!
- Guardado 6 gracias a @ovs
Usamos la expresión x/(b-y)==y/(a-x)que se convierte x*(a-x)==y*(b-y)para evitar verificaciones de módulo.
La expresión calcula la relación entre los lados (el segundo invertido) que tiene que ser el mismo para ser un rectángulo válido.
Perl 5 , ( -p -Minteger) 54 bytes
/ /;$_=grep$_%$'*($'-$_%$')==$_/$'*($`-$_/$'),1..$`*$'
¡Pruébelo en línea! Usando la misma fórmula y rango de producto que ovs, excepto que el rango comienza desde 1
Java 8, 75 bytes
n->k->{int r=0,a=n*k;for(;a-->0;)if(a%n*(n-a%n)==a/n*(k-a/n))r++;return r;}
Port of @ovs 'Python 2 respuesta , ¡así que asegúrate de votarlo!
Pruébelo en línea.
Adelante (gforth) , 72 bytes
: f 0e over 0 do dup 0 do
2dup i - i * swap j - j * = s>f f- loop loop ;
¡Pruébelo en línea!
Otro puerto más de la respuesta de Python 2 de ovs , excepto que usa bucles anidados. Los contadores de bucle directo son mucho más económicos cuando se necesitan varias copias.
Toma n kde la pila principal y devuelve el recuento a través de la pila FP.
: f ( n k -- f:cnt )
0e \ setup the initial count
over 0 do \ outer loop (j): 0 to n-1
dup 0 do \ inner loop (i): 0 to k-1
2dup \ ( n k n k )
i - i * swap \ ( n k i*[k-i] n )
j - j * = \ ( n k i*[k-i]==j*[n-j] ) Forth boolean is 0/-1
s>f f- \ increment count if equal
loop
loop
;