Rectangles en rectangles
Ce défi de code-golf vous donnera deux entiers positifs net kcomme entrées et vous fera compter le nombre de rectangles avec des coordonnées entières qui peuvent être dessinés avec des sommets touchant les quatre côtés du \$n \times k\$ rectangle $$ \{(x,y) : 0 \leq x \leq n, 0 \leq y \leq k\}. $$ Autrement dit, il devrait y avoir:
- au moins un sommet avec un \$x\$-coordonné de \$0\$,
- au moins un sommet avec un \$x\$-coordonné de \$n\$,
- au moins un sommet avec un \$y\$-coordonné de \$0\$, et
- au moins un sommet avec un \$y\$-coordonné de \$k\$.
Exemple
Il y a \$a(5,7) = 5\$rectangles avec des coordonnées entières touchant les quatre côtés d'un \$5 \times 7\$ rectangle:
Table
Le triangle inférieur de la table (symétrique) de \$a(n,k)\$pour \$n,k \leq 12\$ est
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
C'est un défi de code-golf , donc le code le plus court l'emporte.
Réponses
05AB1E , 10 8 octets
LDI-*`¢O
Essayez-le en ligne!
Commenté :
# 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 octets
lambda n,k:sum(a%n*(n-a%n)==a/n*(k-a/n)for a in range(n*k))
Essayez-le en ligne!
Chaque rectangle possible à l'intérieur du \$n \times k\$-rectangle peut être spécifié par deux entiers, \$0 \le a \lt n\$et \$0 \le b \lt k\$:
Pour vérifier un rectangle donné \$a\$et \$b\$, il suffit de vérifier si un angle est un angle droit. Pour ce faire, je prends le produit scalaire de \$\binom{b}{0}-\binom{0}{a}=\binom{-b}{a}\$et \$\binom{k-b}{n}-\binom{0}{a}=\binom{k-b}{n-a}\$pour vérifier si l'angle à \$\binom{0}{a}\$ est un angle droit:
$$ \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 octets
Enregistré 2 grâce à plafonnier !!!
s;a;f(n,k){for(s=a=n*k;a--;)s-=a%n*(n-a%n)!=a/n*(k-a/n);a=s;}
Essayez-le en ligne!
La réponse Python du port de ovs .
Scala , 65 64 60 51 octets
n=>k=>0 to n*k-1 count(a=>a%n*(n-a%n)==a/n*(k-a/n))
Essayez-le en ligne!
- -1 merci à l' utilisateur !
- -4 grâce aux ovs !
- -9 grâce à Kjetil !
Charbon , 21 octets
NθNηIΣEθ№Eη×λ⁻ηλ×ι⁻θι
Essayez-le en ligne! Le lien est vers la version verbeuse du code. Explication: Calcule \$ x(n-x) \$pour \$ 0 \le x < n \$et \$ y(n-y) \$pour \$ 0 \le y < k \$et compte le nombre de fois qu'un entier apparaît dans les deux listes, ce qui correspond au parallélogramme avec les coordonnées \$ (x, 0), (0, y), (n - x, 0), (0, k - y) \$ ayant des angles de 90 degrés:
NθNη
Entrée \$ n \$et \$ k \$.
IΣ
Affiche la somme totale de toutes les correspondances trouvées.
Eη×λ⁻ηλ
Calculer \$ y(n-y) \$pour \$ 0 \le y < k \$.
Eθ№...×ι⁻θι
Calculer \$ x(n-x) \$pour \$ 0 \le x < n \$ et comptez combien de fois chaque entier apparaît dans l'autre liste.
JavaScript (ES6), 63 58 56 octets
Sauvegardé 2 octets grâce à @ovs
(n,y=x=0)=>g=k=>(x=x||++y*k--&&n)&&(y*k==--x*(n-x))+g(k)
Essayez-le en ligne!
Rétine , 45 octets
\d+
*
L$w`(_+) (_+) $.`*$1=$.2*$' m`^(.*)=\1$
Essayez-le en ligne! Le lien comprend une suite de tests. Prend des entrées séparées par des espaces. Explication:
\d+
*
Convertissez les entrées en unaire.
L$w`(_+) (_+)
Correspond à toutes les sous-chaînes qui contiennent _ _. Cela correspond à toutes les paires de \ $ 0 \ le x <n \ $ et \ $ 0 \ le y <k \ $ qui sont représentées par les parties sans correspondance au début et à la fin de la chaîne $`et $'respectivement tandis que \ $ n - x \ $ et \ $ k - y \ $ sont respectivement représentés par $1et $2.
$.`*$1=$.2*$'
Pour chaque paire, listez les produits (unaires) \ $ x (n - x) \ $ et \ $ y (k - y) \ $ .
m`^(.*)=\1$
Comptez le nombre de fois où ils sont égaux.
Gelée , 8 octets
r1×ḶċⱮ/S
Un lien monadique acceptant une paire d'entiers qui donne le décompte.
Essayez-le en ligne! Ou voir la suite de tests .
Comment?
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 octets
a#b=sum[1|x<-[1..a],y<-[1..b],x*(a-x)==y*(b-y)]
Essayez-le en ligne!
- Enregistré 6 grâce à @ovs
Nous utilisons l'expression x/(b-y)==y/(a-x)qui est convertie en x*(a-x)==y*(b-y)pour éviter les vérifications modulo.
L'expression calcule le rapport entre les côtés (le deuxième inversé) qui doit être le même pour être un rectangle valide.
Perl 5 , ( -p -Minteger) 54 octets
/ /;$_=grep$_%$'*($'-$_%$')==$_/$'*($`-$_/$'),1..$`*$'
Essayez-le en ligne! En utilisant la même formule et la même gamme de produits que ovs sauf que la gamme commence à 1
Java 8, 75 octets
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 de la réponse Python 2 de @ovs , alors assurez-vous de le voter!
Essayez-le en ligne.
Forth (gforth) , 72 octets
: f 0e over 0 do dup 0 do
2dup i - i * swap j - j * = s>f f- loop loop ;
Essayez-le en ligne!
Encore un autre portage de la réponse Python 2 d' ovs , sauf qu'il utilise des boucles imbriquées. Les compteurs en boucle directe sont beaucoup moins chers lorsque plusieurs copies sont nécessaires.
Prend n kde la pile principale et renvoie le compte via la pile 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
;