Défi
L'origami (papier pliant) est une forme d'art créative. Pour autant que je sache, le maître d'Origami préfère le papier carré. Commençons par le début - convertissons un papier rectangulaire en papier carré.
Le papier est donc divisé en carrés. Nous supprimons le plus grand carré qui partage un bord plus court avec la forme actuelle, étape par étape (voir l'image ci-dessous). Et si la partie restante après une étape est inférieure ou égale à 0.001 * (area of the original paper)
, le papier ne peut plus être divisé. Il est possible que rien ne reste enfin.
Votre tâche consiste à calculer le nombre de carrés créés au cours du processus. Le carré de la dernière étape qui empêche le papier d'être divisé est compté dans la sortie.
Exemple (un papier de 1.350
largeur / hauteur), la sortie est 10:
Entrée et sortie
Entrée: rapport largeur / hauteur pour le papier rectangulaire, une décimale (ou un entier sans le point) de 1.002
à 1.999
avec un pas minimal de 0.001
. Vous pouvez également utiliser tout autre format raisonnable décrivant le rapport. Mentionnez-le simplement dans votre réponse.
Sortie: nombre carré, un entier.
Exemple d'E / S
Un format de mappage est utilisé pour garder la page bien rangée, tandis que votre code n'a pas besoin de prendre en charge une entrée de liste ni d'être une fonction de mappage.
1.002 => 251
1.003 => 223
1.004 => 189
1.005 => 161
1.006 => 140
1.007 => 124
1.008 => 111
1.009 => 100
Grâce à @LuisMendo, voici le graphique des réponses.
Remarques
- Ceci est un code-golf donc le code le plus court gagne
- Faites attention aux failles standard
- C'est à vous de décider comment gérer les entrées et les sorties, mais elles doivent respecter les restrictions standard.
Au fait...
- Commentez si vous avez quelque chose de peu clair sur le défi
- Personnellement, je dirais que votre réponse contient une explication si vous utilisez une langue de golf
- Merci à @GregMartin, lisez sa réponse pour une bonne explication mathématique du défi.
Exemple de code
Voici une version non golfée du code C ++:
#include <iostream>
#include <utility>
int f (double m)
{
double n = 1, k = 0.001;
int cnt = 0;
k *= m; // the target minimum size
while(m*n >= k)
{
m -= n; // extract a square
if(n > m)
std::swap(n, m); // keep m > n
++ cnt;
}
return cnt;
}
int main()
{
double p;
std::cin >> p;
std::cout << f(p);
return 0;
}
Tous les calculs liés à l'exemple de code nécessitent une précision de 6 chiffres décimaux, qui est couverte par float
.
Réponses:
MATL , 19 octets
L'entrée est un tableau avec les deux nombres définissant le rapport d'origine, tels que
[1, 1.009]
. (Il n'est pas nécessaire que les numéros soient triés ou que l'un d'eux soit 1.)Essayez-le en ligne!
Explication
la source
Haskell ,
71 70 65 63 62 61 5856 octetsMerci à @xnor pour quelques améliorations ingénieuses!
Essayez-le en ligne!
la source
m==n
fin peut être1>0
parce que c'est la seule possibilité qui reste. Ou, peut-être que les cas pourraient être réorganisés pour permettre une liaison ici.n>m
est étendu àn>=m
et que la première vérification est écritee>m*n*1000
, cela devrait donner l'1
égalité.(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1;n!m=n#m$n*m
d<-n-m
commeotherwise
c'est vraiment bien !!!JavaScript (ES6),
5958 octetsTester
Afficher l'extrait de code
la source
Mathematica, non-non concurrentiel (21 octets)
Cette réponse n'est pas concurrente car elle ne répond pas à la vraie question posée! Mais il répond à une variante de la question et fournit une excuse pour mettre en évidence des mathématiques intéressantes.
Fonction symbolique prenant en entrée un nombre rationnel positif (dont le numérateur et le dénominateur représentent les dimensions du papier d'origine) et renvoyant un entier positif. Par exemple,
Tr@*ContinuedFraction[1350/1000]
renvoie10
. (ContinuedFraction
agit différemment sur les nombres à virgule flottante en raison de problèmes de précision, c'est pourquoi un nombre rationnel est nécessaire en entrée dans ce contexte.)Une interprétation intéressante de la procédure géométrique décrite dans le problème (couper des carrés d'un rectangle à plusieurs reprises) est qu'il s'agit d'une implémentation de l'algorithme euclidien pour trouver les plus grands diviseurs communs! Considérez l'exemple dans la question elle-même, avec un ratio
1.35
, qui pourrait être modélisé en ayant un morceau de papier avec des dimensions (1350,1000). Chaque fois qu'un carré est coupé, le plus petit nombre est soustrait du plus grand nombre; donc les rectangles résultants dans cet exemple ont des dimensions (350,1000), puis (350,650), puis (350,300), puis (50,300), puis (50,250) et (50,200) et (50,150) et (50,100) et (50, 50), et aussi (50,0) une fois que nous avons retiré le dernier carré de lui-même. C'est exactement ainsi que fonctionne l'algorithme euclidien (modulo la différence entre division et soustraction répétée), et en effet on voit que 50 est bien le GCD de 1350 et 1000.Typiquement dans l'algorithme euclidien, on garde une trace de ces dimensions intermédiaires et rejette le nombre de soustractions; cependant, on peut alternativement enregistrer combien de fois nous avons soustrait un nombre de l'autre avant que la différence ne devienne trop petite et nous devons changer ce que nous soustrayons. Cette méthode d'enregistrement est précisément la fraction continue d'un nombre rationnel. (Les fractions continues de nombres irrationnels, qui ne se terminent jamais, sont également super cool, mais pas pertinentes ici.) Par exemple, dans l'exemple 1350/1000, nous avons soustrait 1000
1
fois, puis 3502
fois, puis 3001
fois, puis 506
fois; par conséquent, la fraction continue de 1350/1000 est{1,2,1,6}
. Mathématiquement, nous avons réécrit 1350/1000 en1
+ 1 / (2
+ 1 / (1
+ 1 /6
)), que vous pouvez vérifier.Donc, pour ce problème, si vous ne vous arrêtez pas lorsque les carrés deviennent plus petits qu'un certain seuil, mais comptez simplement tous les nombres finis de carrés avant qu'il ne s'arrête, alors le nombre total de carrés est égal au nombre total de soustractions, c'est-à-dire la somme de tous les entiers de la fraction continue - et c'est précisément ce que
Tr@*ContinuedFraction
calcule la composition des fonctions ! (Pour l'exemple donné 1.35, il obtient la réponse que désire l'OP, car le carré final est suffisamment grand pour que tous les carrés soient comptés. MaisTr@*ContinuedFraction[1001/1000]
, par exemple, donne1001
, car il compte le grand carré et les 1000 petits carrés 1x1000. .)la source
Mathematica,
6453 octetsUne solution impérative (style C) a exactement la même longueur:
la source
C (GCC / Clang),
6159 octetsL'entrée est deux entiers (largeur et hauteur) sans point, tels que
f(1999,1000)
.J'espère que quelqu'un pourrait économiser un octet en poussant C dans le club de 58 octets. ;)
la source
m-=n
C, 59 octets
Essayez-le en ligne
L'entrée est un entier qui est le rapport largeur / hauteur en millièmes (par exemple 1002 pour 1,002: 1).
Version non golfée
la source