Boucliers de l'armée romaine

26

Publication sandbox (supprimée)

Les anciennes formations de l'armée romaine sont très célèbres dans le monde entier. Dans ces formations, des légionnaires romains regroupés sous une forme géométrique (généralement un rectangle) protégeant les flancs et la partie supérieure de celui-ci à l'aide de leurs boucliers. Les légionnaires aux positions intérieures couvraient la partie supérieure en plaçant leur bouclier au-dessus de leur tête, les légionnaires sur les flancs portaient 2 boucliers ou plus: un pour protéger la partie supérieure et un ou plusieurs boucliers pour protéger les flancs (si quelqu'un était dans le coin) il avait 3 boucliers, si quelqu'un était seul dans une formation, il avait 5 boucliers Oui, je sais qu'il est impossible pour un humain de porter 5 boucliers, mais ils l'ont fait d'une manière ou d'une autre ). En utilisant cette formation, tous les légionnaires romains se protégeaient et étaient l'adversaire le plus dur à l'époque.

L'histoire raconte qu'il y avait un général romain qui a déclaré que la meilleure forme de formation était le carré (même nombre de légionnaires en rangées et en colonnes). Le problème était de savoir combien de formations (et la taille) il devrait diviser son armée afin de:

  • Ne laissez aucun légionnaire hors d'une formation (bien qu'il ait admis une formation de légionnaire unique)
  • Réduisez la quantité de boucliers requis

Le général, après avoir fait quelques calculs et calculs, il a compris que la meilleure façon d'accomplir ces 2 conditions est de commencer avec le plus grand carré possible, puis de répéter jusqu'à ce qu'il ne reste plus de légionnaires .


Exemple:

Si 35 légionnaires de son armée, la formation consistait à

  • Une place des légionnaires 5x5 (c'est la plus grande place possible).

Avec les légionnaires restants (10)

  • Un carré 3x3

Avec les légionnaires restants (1)

  • Un carré 1x1.

À la fin, cela ressemblera à ceci:

   5x5      
* * * * *        3x3            
* * * * *       * * *      1x1  
* * * * *       * * *       *
* * * * *       * * *       
* * * * *               

Les légionnaires en position intérieure couvraient la partie supérieure en plaçant leur bouclier au-dessus de leurs têtes . Ils n'avaient besoin que d'un bouclier.

* * * * *                   
* 1 1 1 *       * * *       
* 1 1 1 *       * 1 *       *
* 1 1 1 *       * * *       
* * * * *               

Les légionnaires aux flancs portaient 2

* 2 2 2 *                   
2 1 1 1 2       * 2 *       
2 1 1 1 2       2 1 2       *
2 1 1 1 2       * 2 *       
* 2 2 2 *               

Si quelqu'un était dans le coin, il avait 3 boucliers

3 2 2 2 3               
2 1 1 1 2       3 2 3       
2 1 1 1 2       2 1 2       *
2 1 1 1 2       3 2 3       
3 2 2 2 3               

Si quelqu'un était seul dans une formation, il avait 5 boucliers

3 2 2 2 3               
2 1 1 1 2       3 2 3       
2 1 1 1 2       2 1 2       5
2 1 1 1 2       3 2 3       
3 2 2 2 3               

Cette formation a nécessité un total de 71 boucliers.


Défi

  • Calculez la quantité de boucliers nécessaires pour un nombre X de légionnaires

Contribution

  • Nombre de légionnaires dans l'armée

Sortie

  • Quantité de boucliers nécessaires.

Cas de test

35 => 71
20 => 44
10 => 26
32 => 72

  • Les règles de standard s'appliquent
Luis felipe De jesus Munoz
la source
11
Eh bien, le résultat de Google pour "porter 5 boucliers" est Amazon.com : Best-selling Nipple Shield Carrying Case, Perfect...donc je suppose que je ne le saurai jamais vraiment. Portaient-ils en fait 5 boucliers - ou était-ce pour que la question fonctionne: P?
Urne de poulpe magique
1
@MagicOctopusUrn Je suis sûr que vous connaissez la réponse xD Je ne pense pas que quelqu'un ait le courage de sortir dans un combat avec 5 boucliers
Luis felipe De jesus Munoz
4
Je ne pense pas que les calculs et calculs du général aient raison de conclure que la prise répétée du plus grand carré possible minimise les boucliers. Par exemple, 32 légionnaires peuvent se diviser en deux carrés 4 * 4 pour 64 boucliers totaux, plutôt que des carrés de 5 * 5 + 2 * 2 + 1 * 1 + 1 * 1 + 1 * 1 pour 72 boucliers totaux.
xnor
6
@xnor Peut-être qu'en général, le général n'avait pas raison, mais le général est le général (bien qu'il ne faille pas généraliser).
pajonk
2
@AJFaraday Astérix et les blaireaux mercenaires ?
Chris H

Réponses:

14

Python 2 , 60 50 48 octets

def f(s):n=s**.5//1;return s and(n+4)*n+f(s-n*n)

Essayez-le en ligne!

Nouveau au golf de code, mais en lui donnant mon meilleur swing!

Méthode:

Additionnez n^2 + 4nnest chacun des plus grands nombres carrés qui additionnent à l'entrée.

Modifier 1

Réduit à 50 octets grâce à @Jonathan Frech!

Modifier 2

Passé int(s**.5)à s**.5//1économiser 2 octets grâce à @ovs

Easton Bornemeier
la source
8
Bienvenue chez PPCG!
Luis felipe De jesus Munoz
2
Je pense que n*nc'est plus court que n**2de vous faire économiser deux octets; plus que je ne peux pas dire puisque je n'écris pas de python ...
Giuseppe
2
50 octets .
Jonathan Frech
2
int(s**.5)peut être raccourci s**.5//1.
ovs
2
@mypetlion C'est le cas. //est la division du plancher dans Python 2 et 3. est 3**.5//1évaluée 1.0dans les deux versions.
ovs
11

R , 51 50 octets

f=function(x,y=x^.5%/%1)"if"(x,y^2+4*y+f(x-y^2),0)

Essayez-le en ligne!

Un carré de longueur latérale doit avoir exactement des écrans y 2 + 4 y . Nous réduisons par le plus grand carré inférieur ou égal à x jusqu'à ce que x soit nul, accumulant le nombre de boucliers au fur et à mesure.yy2+4yxx

Preuve:

y(y2)2y2(y2)2y=1y2+4y5y=1y

Giuseppe
la source
y24y
1
@ToddSewell sûr, c'est l'explication de Arnauld , et il est beaucoup plus élégant, mais c'est la façon dont je l' ai approché, donc je suis coller à lui! Heureusement, ce n'est pas une question de preuve de golf.
Giuseppe
10

JavaScript (ES7), 34 octets

f=n=>n&&(w=n**.5|0)*w+w*4+f(n-w*w)

Essayez-le en ligne!

Comment?

w=nsw

sw=w2+4w

w=3

(323212323)=(s3=21)(111111111)+(3²=9)(111000000)+(001001001)+(000000111)+(100100100)(4×3=12)

La formule vaut pour , comme .s 1 = 5w=1s1=5

Arnauld
la source
4

Julia 0,6 , 36 octets

!n=(s=isqrt(n))*s+4s+(n>0&&!(n-s*s))

Essayez-le en ligne!

Utilise la même méthode que la réponse R de @ Giuseppe, bien que ma méthode pour y arriver impliquait une réflexion moins significative et une inspection visuelle plus juste: le carré intérieur de 1s a des dimensions par , ce qui a boucliers. Autour de cela, il y a 4 murs de soldats chacun, chacun avec 2 boucliers - ce qui ajoute boucliers. Enfin, il y a quatre 3 aux quatre coins, ce qui ajoute 12 boucliers.n2+4n(n2)(n2)(n2)2n24(n2)2

(n2)2+4(n2)2+43=n2+44n+8n16+12=n2+4n

Non golfé:

!n = begin       # Assign to ! operator to save bytes on function parantheses
  s = isqrt(n)   # Integer square root: the largest integer m such that m*m <= n
  s * s +
    4 * s +
      (n > 0 &&  # evaluates to false = 0 when n = 0, otherwise recurses
        !(n - s * s))
end

(Cela peut également être fait en 35 octets avec n>0?(s=isqrt(n))*s+4s+f(n-s*s):0, mais j'ai écrit cela pour Julia 0.7 voulait éviter les nouveaux avertissements de dépréciation (les espaces exigeant sont ?et :).)

Sundar - Rétablir Monica
la source
Une autre explication trop compliquée pour le nombre de boucliers, voir mon commentaire sur la réponse de @ Giuseppe.
Todd Sewell
2
@ToddSewell Oui, l'aire + périmètre est une façon plus élégante de voir les choses. Je ne l'ai pas fait de cette façon cependant, et comme Giuseppe, mon intention est de décrire mon approche plutôt que de donner la preuve la plus nette de la formule.
sundar
3

Brachylog , 26 octets

0|⟧^₂ᵐ∋N&;N-ℕ↰R∧N√ȧ×₄;N,R+

Essayez-le en ligne!

0           % The output is 0 if input is 0
|           % Otherwise,
⟧           % Form decreasing range from input I to 0
^₂ᵐ         % Get the squares of each of those numbers
∋N          % There is a number N in that list
&;N-ℕ       % With I - N being a natural number >= 0 i.e. N <= I
            % Since we formed a decreasing range, this will find the largest such number
↰           % Call this predicate recursively with that difference I - N as the input
R           % Let the result of that be R
∧N√ȧ        % Get the positive square root of N
×₄          % Multiply by 4
;N,R+       % Add N and R to that
            % The result is the (implicit) output
Sundar - Rétablir Monica
la source
2

Retina 0.8.2 , 28 octets

.+
$*
(\G1|11\1)+
$&11$1$1
.

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

.+
$*

Convertissez en décimal.

(\G1|11\1)+

Faites correspondre les nombres impairs. Le premier passage dans le groupe \1n'existe pas encore, donc seul \G1peut correspondre, ce qui correspond à 1. Les correspondances suivantes ne peuvent pas correspondre \G1car \Gseules les correspondances au début du match, donc à la place nous devons faire correspondre ce 11\1qui est 2 de plus que le match précédent. Nous faisons correspondre autant de nombres impairs que possible, et la correspondance totale est donc un nombre carré, tandis que la dernière capture est inférieure à deux fois son côté.

$&11$1$1

Ajoutez les protections latérales à chaque match. $&est et est alors que nous avons besoin de .n2$12n1n2+4n=n2+2+2(2n1)

.

Additionnez et convertissez en décimal.

Neil
la source
2

05AB1E , 17 octets

[Ð_#tïÐns4*+Šn-}O

Essayez-le en ligne ou vérifiez tous les cas de test .

Contournement parce que ΔDtïÐns4*+Šn-}O( 15 octets ) ne semble pas fonctionner. Essayez-le en ligne en mode débogage pour voir ce que je veux dire. Je m'attendrais à ce qu'il passe de [45,'35',25]à [45,10]après l' -itération suivante et suivante Δ, mais apparemment, il efface la pile à l'exception de la dernière valeur et devient [10], ce qui entraîne 0 à la fin .. Je ne sais pas si c'est un comportement prévu ou un bogue .. (EDIT: C'est prévu, voir en bas.)

Explication:

Utilise également où est la largeur d'une boucle comme la plupart des autres réponses.ww2+4ww

[        }     # Start an infinite loop:
 Ð             #  Triplicate the value at the top of the stack
  _#           #  If the top is 0: break the infinite loop
 t             #  Take the square-root of the value
               #   i.e. 35 → 5.916...
  ï            #  Remove any digits by casting it to an integer, so we have our width
               #   i.e. 5.916... → 5
   Ð           #  Triplicate that width
    n          #  Take the square of it
               #   i.e. 5 → 25
     s         #  Swap so the width is at the top again
      4*       #  Multiply the width by 4
               #   i.e. 5 → 20
        +      #  And sum them together
               #   i.e. 25 + 20 → 45
 Š             #  Triple-swap so the calculated value for the current width
               #  is now at the back of the stack
               #   i.e. [35,5,45] → [45,35,5]
  n            #  Take the square of the width again
               #   5 → 25
   -           #  Subtract the square of the width from the value for the next iteration
               #   i.e. 35 - 25 → 10
          O    # Take the sum of the stack
               #   i.e. [45,21,5,0,0] → 71

EDIT: Apparemment, le comportement que j'ai décrit ci-dessus Δest destiné. Voici deux alternatives de 17 octets fournies par @ Mr.Xcoder qui utilisent Δen mettant des valeurs dans le global_array (avec ^) et en les récupérant ensuite (avec ¯):

ΔЈtïnα}¯¥ÄDt··+O

Essayez-le en ligne ou vérifiez tous les cas de test .

ΔЈtïnα}¯¥ÄtD4+*O

Essayez-le en ligne ou vérifiez tous les cas de test .

Kevin Cruijssen
la source
2

dc , 25 octets

d[dvddSa*-d0<MLa+]dsMx4*+

Essayez-le en ligne!

Calcule les boucliers comme sum(n^2)(le nombre d'origine) plus 4*sum(n)en poussant une copie de chaque longueur de côté carré dans le registre de pile au afur et à mesure, puis en ajoutant toutes les valeurs du registre acomme la récursion "se déroule".

Sophia Lechner
la source
2

APL (Dyalog Unicode) , 31 30 octets

{⍵<2:⍵×5⋄(S×S+4)+∇⍵-×⍨S←⌊⍵*.5}

Essayez-le en ligne!

-1 octet grâce à @jslip

Zacharý
la source
0,5 -> 0,5 pour 1 octet
jslip
Wow, comment ai-je raté ça
Zacharý
1

PHP , 67 octets

<?for($n=$argv[1];$w=(int)sqrt($n);$n-=$w**2)$a+=$w**2+$w*4;echo$a;

Pour l'exécuter:

php -n <filename> <n>

Exemple:

php -n roman_army_shields.php 35

Ou essayez-le en ligne!


En utilisant l' -Roption, cette version fait 60 octets :

for(;$w=(int)sqrt($argn);$argn-=$w**2)$a+=$w**2+$w*4;echo$a;

Exemple:

echo 35 | php -nR "for(;$w=(int)sqrt($argn);$argn-=$w**2)$a+=$w**2+$w*4;echo$a;"

(sous Linux, remplacer "par ')


Remarque: Ceci utilise la grande formule de réponse d'Arnauld , je n'ai pas pu trouver quelque chose de plus court que cela.

Nuit2
la source
1

Pyth , 19 octets

Une fonction récursive, qui devrait être appelée en utilisant y(voir le lien).

L&b+*Ks@b2+4Ky-b^K2

Essayez-le ici!

Pyth , 21 octets

L'historique des révisions est assez drôle, mais assurez-vous de le visiter si vous voulez une version beaucoup plus rapide :)

sm*d+4deeDsI#I#@RL2./

Essayez-le ici!

Explication

sm*d+4deeDsI#I#@RL2./ Programme complet, appelons l'entrée Q.
                   ./ Partitions entières de Q. Donne toutes les combinaisons de positifs
                          entiers qui totalisent Q.
               @ RL2 Prenez la racine carrée de tous les entiers de chaque partition.
             I # Conservez uniquement les partitions invariantes sous:
          sI # Jeter tous les non-entiers. Cela ne fait que maintenir
                          des partitions entièrement constituées de carrés parfaits, mais
                          au lieu d'avoir les carrés eux-mêmes, nous avons leurs racines.
       eeD Obtenez la partition (disons P) avec le maximum le plus élevé.
 m Pour chaque d dans P ...
  * d + 4d ... Rendement d * (d + 4) = d ^ 2 + 4d, la formule utilisée dans toutes les réponses.
s Additionnez les résultats de ce mappage et sortez implicitement.
M. Xcoder
la source
1

Swift 4 , 111 99 84 78 octets

func f(_ x:Int)->Int{var y=x;while y*y>x{y-=1};return x>0 ?(y+4)*y+f(x-y*y):0}

Essayez-le en ligne!

Cette sensation lors de l'implémentation manuelle de la racine carrée entière est beaucoup plus courte que celle intégrée ...

Non golfé et expliqué

// Define a function f that takes an integer, x, and returns another integer
// "_" is used here to make the parameter anonymous (f(x:...) -> f(...))
func f(_ x: Int) -> Int {

    // Assign a variable y to the value of x

    var y = x

    // While y squared is higher than x, decrement y.

    while y * y > x {
        y -= 1
    }

    // If x > 0, return (y + 4) * y + f(x - y * y), else 0.

    return x > 0 ? (y + 4) * y + f(x - y * y) : 0
}
M. Xcoder
la source