Vous enseignez à une classe d'élèves ayant des préférences intéressantes quant à la disposition de leurs chaises. Il y a 3 exigences très spécifiques pour la disposition des chaises:
La plupart sont disposées dans un rectangle, même si cela signifie que certaines chaises sont vides.
Il doit y avoir aussi peu de chaises vides que possible.
Ils doivent être aussi "carrés" que possible. La carréité est déterminée par la distance entre la largeur et la hauteur du rectangle, plus c'est bas, mieux c'est. Par exemple, un rectangle qui
4x7
a un carré de 3.
Pour être plus précis, le «score» d'un arrangement est la distance entre la largeur et la hauteur plus le nombre de chaises qui se videraient.
Prenons un exemple. Disons que vous avez 13 étudiants. Vous pouvez organiser les chaises de l'une des manières suivantes:
1x13
2x7
3x5
4x4
1x13
n'est pas très carré. En fait, 1 et 13 sont séparés de 12, nous donnons donc à cet arrangement 12 points. Il a également 0 chaises vides, nous ajoutons donc 0 points, ce qui donne à cet arrangement un score de 12. Pas terrible.
2x7
c'est certainement mieux. 2 et 7 ne sont séparés que par 5, nous accordons donc 5 points à cet arrangement. Cependant, si vous disposiez réellement 2 rangées de sept chaises, cela prendrait 14 chaises, ce qui signifie qu'une chaise serait vide. Nous ajoutons donc un point, donnant à cet arrangement un score de 6.
On pourrait aussi faire 3x5
. 3 et 5 sont à 2, donc +2 points. Cela prend 15 chaises, ce qui signifie que nous aurions deux chaises supplémentaires, donc encore +2 points, pour un score de 4.
La dernière option, 4x4
. 4 et 4 sont 0 à part, donc nous donnons ce +0 points. 4x4 prend 16 chaises, donc 3 chaises sont vides, pour un score total de 3. C'est la solution optimale.
En cas d'égalité, la solution optimale est celle avec moins de chaises vides.
Le défi
Vous devez écrire un programme ou une fonction qui prend un nombre entier et génère la disposition optimale des chaises pour ce nombre d'élèves. IO peut être dans n'importe quel format raisonnable. Voici un exemple de sortie pour n'importe quel nombre d'élèves de 1 à 100:
1: (1, 1)
2: (1, 2)
3: (2, 2)
4: (2, 2)
5: (2, 3)
6: (2, 3)
7: (3, 3)
8: (3, 3)
9: (3, 3)
10: (2, 5)
11: (3, 4)
12: (3, 4)
13: (4, 4)
14: (4, 4)
15: (4, 4)
16: (4, 4)
17: (3, 6)
18: (3, 6)
19: (4, 5)
20: (4, 5)
21: (3, 7)
22: (5, 5)
23: (5, 5)
24: (5, 5)
25: (5, 5)
26: (4, 7)
27: (4, 7)
28: (4, 7)
29: (5, 6)
30: (5, 6)
31: (4, 8)
32: (4, 8)
33: (6, 6)
34: (6, 6)
35: (6, 6)
36: (6, 6)
37: (5, 8)
38: (5, 8)
39: (5, 8)
40: (5, 8)
41: (6, 7)
42: (6, 7)
43: (5, 9)
44: (5, 9)
45: (5, 9)
46: (7, 7)
47: (7, 7)
48: (7, 7)
49: (7, 7)
50: (5, 10)
51: (6, 9)
52: (6, 9)
53: (6, 9)
54: (6, 9)
55: (7, 8)
56: (7, 8)
57: (6, 10)
58: (6, 10)
59: (6, 10)
60: (6, 10)
61: (8, 8)
62: (8, 8)
63: (8, 8)
64: (8, 8)
65: (6, 11)
66: (6, 11)
67: (7, 10)
68: (7, 10)
69: (7, 10)
70: (7, 10)
71: (8, 9)
72: (8, 9)
73: (7, 11)
74: (7, 11)
75: (7, 11)
76: (7, 11)
77: (7, 11)
78: (9, 9)
79: (9, 9)
80: (9, 9)
81: (9, 9)
82: (7, 12)
83: (7, 12)
84: (7, 12)
85: (8, 11)
86: (8, 11)
87: (8, 11)
88: (8, 11)
89: (9, 10)
90: (9, 10)
91: (7, 13)
92: (8, 12)
93: (8, 12)
94: (8, 12)
95: (8, 12)
96: (8, 12)
97: (10, 10)
98: (10, 10)
99: (10, 10)
100: (10, 10)
Comme d'habitude, il s'agit de code-golf, donc les échappatoires standard s'appliquent, et le gagnant est la réponse la plus courte en octets.
Réponses:
Gelée ,
161514 octetsEssayez-le en ligne! ou vérifiez tous les cas de test .
Comment ça fonctionne
la source
Python 2, 68 octets
Équivalent au plus «évident»:
la source
range(-n,0)
, comme je le fais dans ma réponse . Suite de tests.Haskell, 65 octets
Exemple d'utilisation:
map f [1..5]
->[(1,1),(1,2),(2,2),(2,2),(2,3)]
.Traverse une boucle externe
a
de1
àx
(x -> nombre d'élèves) et une boucle interneb
de1
àa
. Conserve tout(b,a)
oùa*b>=x
et construit des paires((arrangement points,seats left), (b,a))
qui suivent l'ordre lexicographique dont nous avons besoin pour trouver le minimum. Remarque:a
est toujours supérieur àb
, nous n'avons donc pas besoinabs
de carré. Pas besoin de soustrairex
du score "places restantes", car seul l'ordre relatif compte. Enfin, nous supprimons la paire de scores avecsnd
.la source
a*b
(nombre de places libres) est le bris d'égalité si le score principal est égal. Par exemplen=43
: a)a=7, b=7
, score:(49,49)
b)a=9, b=5
, le score:(49,45)
. Le score principal est égal, le bris d'égalité décide, b) gagne.a*b
, les chiffres(b,a)
que je dois porter de toute façon agissent comme le casse-cravate et donnent les mêmes résultats pour (au moins)n=1..300
. Un produit est petit si l'un des facteurs (icib
) est petit. Mais tant que je n'ai pas de preuve formelle, je ne veux pas utiliser ce fait. Voyons voir si j'en trouve un.Ruby, 64 octets
Une lambada qui prend le nombre de personnes en argument et renvoie un tableau avec la largeur et la hauteur de la solution optimale.
la source
w*h
comme deuxième élément de votre tableau? Je ne pense pas que cela change particulièrement quoi que ce soit lorsque vous appelezmin
parce que vous minimisez le score aka le premier élément.In case of a tie, the optimal solution is the one with less empty chairs
MATL , 18 octets
Essayez-le en ligne!
Explication
la source
Javascript, 98 octets
Mon premier code golf, donc je poste quand même!
Au départ,
o
c'était un objet vide et j'ai vérifié s'ilo.a
était vide, donc c'était un cas spécial au premier tour. Mais j'ai trouvé l'astuce 1/0 dans la réponse d'edc65 pour initialiser la variable sur Infinity.la source
Pyth,
242221 octetsEdit : dans la clé de tri, je me rends compte qu'il n'est pas nécessaire de trouver le nombre de chaises vides. C'est équivalent à marquer le nombre total de chaises. Cela m'a fait gagner 2 octets.
Essayez-le en ligne!
la source
Matlab
(174) (146)121astuce 1: j'ai ajouté le montant
1-1/length*width
comme pointageastuce 2: j'ai calculé le
number_students/length
plafond pour la largeur du rectangle,la limite supérieure est le carré mais aussi le plafondJe suis sûr qu'il peut être joué plus loin ...
essayez-le
Edit: référencé aux remarques de @StewieGriffin.
Modifier 2:
1
etn
sont des constantes pas besoin de les ajouter au score global.Edit 3: test de performance.
la source
unique
Python 2, 64 octets
Il s'agit d'une fusion de la réponse Python de @ Lynn (d'où j'ai pris l'
max(...)[1:]
astuce) et de l'algorithme de ma réponse Julia (qui permet une implémentation légèrement plus courte).Testez-le sur Ideone .
la source
Julia,
6159555352 octetsEssayez-le en ligne!
Comment ça fonctionne
Le code est équivalent à la version non golfée suivante, où
cld
est la division du plafond.Pour trouver l'arrangement optimal, il suffit clairement d'examiner les paires [i, j] , où 1 ≤ i ≤ n et j = ⌈n / i⌉ .
Le score pour un tel arrangement est | j - i | + (ij - n) , où la deuxième somme est le nombre de chaises vides. Au lieu des scores réels, nous pouvons comparer les scores augmentés d'une constante, tels que ij + | j - i | + 1 .
Il suffit de considérer les paires [i, j] où i ≤ j puisque les dispositions [i, j] et [j, i] sont également valables. Nous traitons les paires strictement décroissantes en fixant j = max (⌈n / i⌉, i) à la place, ce qui garantit que j ≥ i et produira un score sous-optimal si ⌈n / i⌉ <i .
Puisque j - i ≥ 0 , on a ij + | j - i | + 1 = ij + j - i + 1 = (i + 1) × (j - 1) , qui peut être calculé en moins d'octets de code.
Enfin
indmin
/indmax
donne l'indice m (et donc la valeur de i ) de l'arrangement optimal, qui est m par ⌈n / m⌉ . Les liens sont rompus par première occurrence, ce qui correspond à la valeur la plus basse de i , donc la valeur la plus élevée de j - i et donc la valeur la plus basse de ij - n (chaises vides).la source
JavaScript (ES6) 74
78Modifier en conservant le résultat temporaire sous forme de tableau au lieu de 2 vars, emprunté à la réponse de Thiht
Moins golfé
Tester
la source
PHP, 129 octets
Non golfé:
la source
PHP, 104 octets
L'algorithme qui résout ce problème est simple et il est probablement utilisé par d'autres réponses dans des langages similaires à PHP (JavaScript, fe):
n
est suffisamment grand (oùn
est la valeur d'entrée); le score de l'arrangement calculé sur la première itération (1, n
) est(n-1)+0
;1
etn
; calculer la hauteur minimale commeceil(n/width)
, calculer le score d'arrangement en utilisant la formule fournie dans la question (c.-à-d.abs(width - height) + (width * height - n)
); si le score est meilleur que le meilleur score précédent, n'oubliez pas la largeur, la hauteur et le nouveau meilleur score; sur les liens, utilisez la valeur dewidth * height - n
pour l'arrangement actuel et l'ancien meilleur arrangement pour détecter le nouveau meilleur arrangement;Après le golf, cet algorithme produit quelque chose comme ça (enveloppé ici pour plus de lisibilité):
Il utilise 137 octets (lorsqu'il est mis sur une seule ligne) et il est loin des 104 octets annoncés dans le titre. Le code peut probablement être raccourci de 2-3 octets mais la grande source d'amélioration est ailleurs: dans les détails de l'algorithme.
L'algorithme révisé:
Il existe plusieurs endroits où l'algorithme peut être amélioré en supprimant le code inutile.
1
à$n
; pour la vitesse, la largeur ($i
) doit itérer entre1
etfloor(sqrt($n))
mais cela rend le code encore plus long au lieu de le raccourcir; mais si la largeur ne dépasse passqrt($n)
, la hauteur minimale ($j
) sera toujours supérieure àsqrt($n)
(leur produit doit être au moins$n
);$i <= $j
(largeur <= hauteur) comme condition de terminaison pour la boucle; de cette façon, la largeur itérera de1
àfloor(sqrt($n))
et la hauteur obtiendra des valeurs commençant par$n
et descendant versceil(sqrt($n))
(pas nécessairement toutes);abs(width - height)
c'est toujoursheight - width
($j-$i
); 5 octets enregistrés de cette façon;$n
est utilisée dans le calcul du score (le nombre de sièges inoccupés estwidth * height - n
) mais elle n'est pas nécessaire; la partition n'a pas besoin d'être affichée, elle n'est calculée que pour la comparaison des arrangements; en supprimant- n
de la formule de score, nous économisons encore 3 octets (le code PHP l'est-$n
) sans rien perdre;height - width + width * height
($j-$i+$i*$j
);height - width
partie du score diminue à chaque pas;||$c==$s&&$i*$j<$w*$h
- beaucoup d'octets);-$n
de la formule du score, le score pour le premier arrangement (1x$n
) est$n-1+1*$n
(ie2*$n-1
); la valeur initiale du meilleur score ($s
) peut être toute valeur supérieure ou égale à2*$n
; la première itération a un meilleur score et devient le meilleur arrangement permettant à l'algorithme de fonctionner sans problèmes d'initialisation.Le nouveau code ( 104 octets ), après avoir appliqué les améliorations décrites ci-dessus, est:
Il est emballé ici pour plus de lisibilité. Ajoutez le code ci-dessus avec le marqueur PHP
<?php
(techniquement, il ne fait pas partie du code), placez-le dans un fichier (disonsarrange-your-chairs.php
) et exécutez-le avec un entier supérieur à zéro comme argument. Il affichera la largeur et la hauteur de l'arrangement calculé, séparées par une virgule:Une autre solution (116 octets)
Une autre solution qui utilise un algorithme différent:
Il place toutes les combinaisons d'au moins des
$n
sièges dans une liste associative; la clé est la représentation textuelle de l'arrangement, la valeur est le score de l'arrangement. Il trie ensuite la liste (croissant par valeur) et obtient la clé de la première entrée.Un de plus (115 octets)
Ceci est la version PHP de la réponse de @ Neil (JavaScript / ES6, 85 octets).
Il existe des différences notables en raison des caractéristiques de chaque langue:
n
valeurs (non définies) puis utilise ses clés pour itérer de0
àn-1
; il incrémentei
(d=(n+i++)/i|0
) pour le faire itérer de1
àn
; la solution PHP n'a pas besoin d'incrémenter; il utiliserange()
pour générer un tableau puis il utilise les valeurs générées (1
àn
) pour itérer;(n+i)/i
convertit ensuite la valeur en entier en utilisant|0
pour obtenir le plus petit entier plus grand quen/i
; la réponse PHP résout facilement ce problème avec la fonction PHPceil()
; JavaScript fournit également,Math.ceil()
mais il utilise 5 octets de plus que la solution trouvée par Neil;array_map()
qui est en quelque sorte similaire à JSArray.map()
mais cela n'aide pas ici; sa syntaxe est verbeuse, aforeach
produit un code plus court; il est cependant plus grand que le code JS;||
n'est pas possible en PHP car il manque l'opérateur virgule; Je traduisa||b||c
enif(!a&&!b)c
puis, parce quea
etb
des comparaisons, je leurs opérateurs nié (remplacé<
par>=
); cela produit également un code plus volumineux que la version JS;$
.Les versions non golfées de toutes les solutions et la suite de tests peuvent être trouvées sur Github .
la source
JavaSCript (ES6), 83 octets
la source
m
pour compenser.Julia, 87
Je pense que c'est un pas vers la recherche d'une fonction magique pour le problème:
Il ne regarde que les paires
(i, j=(i+n)/(i+1))
ou(i, j+1)
la source
n
nulle part et vous ne semblez pas prendre de contribution.n
comme entrée. Il faudrait l'enveloppern->...
. Ravi que vous puissiez le faire fonctionner.Oracle SQL 11.2, 173 octets
Non golfé
la source
Q 58 octets
Lamba qui calcule le coût minimal pour une valeur donnée (x) et renvoie une séquence de deux valeurs (largeur, hauteur)
L'ajout d'un nom à ce lambda nécessite deux autres caractères (ex f: {..} au lieu de {..})
Tester
où {..} est le lambda. Lire comme "applique lambda à chaque valeur de 1 + 100 premiers pouces" (en d'autres termes à chaque valeur 1..100)
Génère
Explication
La lamdba imbriquée
{((b<a)?1b)#+(b:-_-x%a;a:1+!x)}
génère toutes les paires candidates (largeur, hauteur) pour les chaises x sous la forme de deux séquences (w1 w2 w3 ..; h1 h2 h3 ..) (largeurs et hauteurs). Lire de gauche à droite, mais évaluer de droite à gauchea:1+!x
génère des valeurs 1..x et affecte cette séquence à un-_-
is negate floor negate, et implémente ceil (ceil n'est pas une primitive du langage)b:-_-x%a
applique le plafond à chaque valeur de x divisée par un élément im a et attribue la séquence résultante à b. En d'autres termes, b est ceil chaque x divisé par chaque 1..x+(b;a)
retourner une sécuence composée de seq a et seq b, puis la retourne (le résultat est une séquence de paire où i-pair contient l'élément i de a et l'élément i de b)b<a
compare item par item de b et a, et génère une sécuence de valeurs logiques (true = 1b pour chaque index où b [i]s?x
renvoie la première position de l'élément x dans la séquence s. Avec(b<a)?1b
Nous recherchons 1b (valeur vraie) dans la séquence résultant de la comparaison de b et a, et obtenons la première position où bn#s
prend n premiers n éléments des séquences. Nous voulons éliminer les paires en double, donc nous nous arrêtons lorsque le premier élément d'une paire <le deuxième élément (par exemple, considérons 13,1 mais pas 1,13).Comme effet secondaire, chaque paire de la séquence résultante a une distance décroissante entre a et b (ex (13 1; 7 2; 5 3; 4 4)
La paire candidate générée par lambda imbriquée est affectée à c. Nous inversons ensuite c (obtient à nouveau b, a) et appliquons deux fonctions à cet argument:
*/
multiplie et-/
soustrait. Le résultat(-/;*/)@\:+c
est la différence et le produit de chaque paire.+/
est la somme terminée et calcule le coût final. Le coût de chaque patir est attribué à d& / est un minimum sur, donc
&/
d est le coût minimum. Avecd?&/d
nous trouvons la première occurrence de coût minimum en d, et avec c @ .. nous récupérons la paire à cette position. Comme chaque paire est de distante décroissante entre a et n, le premier minimum trouvé a le distante maximum entre les autres paires minimales, donc nous appliquons correctement la règle de lienla source