Escudos do exército romano

26

Postagem na caixa de areia (excluída)

As antigas formações do exército romano são muito famosas em todo o mundo. Nessas formações, os legionários romanos agrupados em uma forma geométrica (geralmente um retângulo) protegiam os flancos e a parte superior usando seus escudos. Os legionários em posições interiores cobriam a parte superior colocando seu escudo acima de suas cabeças, os legionários nos flancos carregavam 2 ou mais escudos: um para proteger a parte superior e um ou mais escudos para proteger os flancos (se alguém estivesse no canto ele tinha 3 escudos; se alguém estava sozinho em uma formação, ele tinha 5 escudos. Sim, eu sei que é impossível para um humano carregar 5 escudos, mas de alguma forma eles conseguiram ). Usando essa formação, todos os legionários romanos se protegeram e eram o adversário mais difícil da época.

A história conta que havia um general romano que afirmou que a melhor forma de formação era o quadrado (o mesmo número de legionários em linhas e colunas). O problema era descobrir quantas formações (e o tamanho) ele deveria dividir seu exército para:

  • Não deixe nenhum legionário fora de uma formação (embora ele tenha admitido uma formação legionária única)
  • Reduza a quantidade de escudos necessários

O general, depois de fazer algumas contas e cálculos, descobriu que a melhor maneira de cumprir essas 2 condições é começar com o maior quadrado possível e depois repetir até que não sobrem legionários .


Exemplo:

Se 35 legionários em seu exército, a formação consistia em

  • Um quadrado de legionários 5x5 (este é o maior quadrado possível).

Com os legionários restantes (10)

  • Um quadrado 3x3

Com os legionários restantes (1)

  • Um quadrado 1x1.

No final, será algo parecido com isto:

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

Os legionários em posições interiores cobriam a parte superior, colocando o escudo acima da cabeça . Eles só precisavam de 1 escudo.

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

Os legionários nos flancos levavam 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 *               

Se alguém estava no canto, ele tinha 3 escudos

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               

Se alguém estava sozinho em uma formação, ele tinha 5 escudos

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               

Essa formação exigiu um total de 71 escudos.


Desafio

  • Calcular a quantidade de escudos necessários para uma quantidade X de legionários

Entrada

  • Quantidade de legionários no exército

Saída

  • Quantidade de escudos necessários.

Casos de teste

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

Luis felipe De jesus Munoz
fonte
11
Bem, o resultado do google para "carregar 5 escudos" é Amazon.com : Best-selling Nipple Shield Carrying Case, Perfect...então acho que nunca vou realmente saber. Eles realmente carregavam 5 escudos-- ou era para fazer a pergunta funcionar: P?
Magic Octopus Urn
1
@MagicOctopusUrn Im certeza que você sabe a resposta XD Eu não acho que alguém tem a coragem de sair em uma briga com 5 escudos
Luis Felipe de Jesus Munoz
4
Acho que a matemática e os cálculos do general não estão certos ao concluir que tomar repetidamente o maior quadrado possível minimiza os escudos. Por exemplo, 32 legionários podem se dividir em dois quadrados 4 * 4 para 64 escudos no total, em vez de quadrados de 5 * 5 + 2 * 2 + 1 * 1 + 1 * 1 + 1 * 1 para 72 escudos no total.
Xnor
6
@ xnor Talvez, em geral, o general não estivesse certo, mas o general é o general (embora não devamos generalizar).
Pajonk
2
@AJFaraday Asterix e os texugos mercenários ?
21718 Chris H

Respostas:

14

Python 2 , 60 50 48 bytes

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

Experimente online!

Novo no código de golfe, mas dando o meu melhor balanço!

Método:

Soma n^2 + 4nonde nestá cada um dos maiores números quadrados que somam à entrada.

Editar 1

Reduzido para 50 bytes graças a @Jonathan Frech!

Editar 2

Comutado int(s**.5)para s**.5//1salvar 2 bytes graças a @ovs

Easton Bornemeier
fonte
8
Bem-vindo ao PPCG!
Luis felipe De jesus Munoz
2
Eu acho que n*né mais curto do n**2que economizar dois bytes; mais do que isso não posso dizer desde que eu fazer python não escrevo ...
Giuseppe
2
50 bytes .
Jonathan Frech
2
int(s**.5)pode ser reduzido para s**.5//1.
ovs 02/08/19
2
@mypetlion Sim. //é a divisão de piso no Python 2 e 3. é 3**.5//1avaliada 1.0nas duas versões.
ovs 03/08/19
11

R , 51 50 bytes

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

Experimente online!

yy2+4yxx

Prova:

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

Giuseppe
fonte
y24y
1
@ ToddSewell, claro, essa é a explicação de Arnauld , e é muito mais elegante, mas foi assim que me aproximei, por isso estou me atendendo a isso! Felizmente, esta não é uma questão de prova de golfe.
Giuseppe
10

JavaScript (ES7), 34 bytes

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

Experimente online!

Quão?

w=nsw

sw=w2+4w

w=3

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

w=1s1=5

Arnauld
fonte
4

Julia 0.6 , 36 bytes

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

Experimente online!

n2+4n(n-2)(n-2)(n-2)2n-24(n-2)2escudos. Finalmente, existem quatro 3s nos quatro cantos, o que adiciona 12 escudos.

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

Ungolfed:

!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

(Isso também pode ser feito em 35 bytes n>0?(s=isqrt(n))*s+4s+f(n-s*s):0, mas eu escrevi isso para Julia 0.7 queria evitar os novos avisos de descontinuação (os espaços exigidos são ?e :).)

sundar - Restabelecer Monica
fonte
Outra explicação complicada para a contagem de escudos, veja meu comentário na resposta de @ Giuseppe.
Todd Sewell
2
@ToddSewell Sim, área + perímetro é uma maneira mais elegante de olhar para ela. Mas não fiz dessa maneira e, semelhante a Giuseppe, minha intenção é descrever minha abordagem do que dar a prova mais clara da fórmula.
sundar - Restabelece Monica
3

Braquilog , 26 bytes

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

Experimente online!

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 - Restabelecer Monica
fonte
2

Retina 0.8.2 , 28 bytes

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

Experimente online! O link inclui casos de teste. Explicação:

.+
$*

Converta para decimal.

(\G1|11\1)+

Combine números ímpares. A primeira passagem pelo grupo \1ainda não existe, portanto, somente \G1pode corresponder, que corresponde a 1. Correspondências subsequentes não podem corresponder, \G1pois \Gapenas correspondências no início da partida, portanto, temos que corresponder a 11\12 mais do que a partida anterior. Combinamos o maior número possível de números ímpares e, portanto, a correspondência total é um número quadrado, enquanto a última captura é uma menos que o dobro do seu lado.

$&11$1$1

$&n2$12n1n2+4n=n2+2+2(2n1)

.

Soma e converta para decimal.

Neil
fonte
2

05AB1E , 17 bytes

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

Experimente online ou verifique todos os casos de teste .

Solução alternativa porque ΔDtïÐns4*+Šn-}O( 15 bytes ) parece não funcionar .. Experimente online no modo de depuração para entender o que quero dizer. Eu esperaria que ele vá partir [45,'35',25]para [45,10]depois do -e próxima iteração Δ, mas aparentemente ele limpa a pilha, exceto para o último valor e torna-se [10], resultando em 0 no final .. Não tenho certeza se este é o comportamento desejado ou um bug .. (EDIT: Pretende-se, veja abaixo.)

Explicação:

w2+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

Edição: Aparentemente, o comportamento que eu descrevi acima Δé destinado. Aqui estão duas alternativas de 17 bytes fornecidas pelo @ Mr.Xcoder que são usadas Δcolocando valores no global_array (with ^) e recuperando-os novamente depois (com ¯):

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

Experimente online ou verifique todos os casos de teste .

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

Experimente online ou verifique todos os casos de teste .

Kevin Cruijssen
fonte
2

dc , 25 bytes

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

Experimente online!

Calcula os escudos como sum(n^2)(o número original) mais 4*sum(n)empurrando uma cópia do comprimento de cada lado quadrado para o registrador da pilha a, e adicionando todos os valores do registrador à amedida que a recursão "desenrola".

Sophia Lechner
fonte
2

APL (Dyalog Unicode) , 31 30 bytes

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

Experimente online!

-1 byte graças a @jslip

Zacharý
fonte
0,5 -> 0,5 para 1 byte
jslip
Uau, como eu perdi isso
#
1

PHP , 67 bytes

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

Para executá-lo:

php -n <filename> <n>

Exemplo:

php -n roman_army_shields.php 35

Ou Experimente online!


Usando a -Ropção, esta versão tem 60 bytes :

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

Exemplo:

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

(no Linux, substitua "por ')


Nota: Isso está usando a ótima fórmula da resposta de Arnauld , não consegui encontrar nada mais curto que isso.

Night2
fonte
1

Pyth , 19 bytes

Uma função recursiva, que deve ser chamada usando y(consulte o link).

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

Experimente aqui!

Pyth , 21 bytes

O histórico de revisões é bastante engraçado, mas não deixe de visitá-lo se quiser uma versão muito mais rápida :)

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

Experimente aqui!

Explicação

sm*d+4deeDsI#I#@RL2./ Programa completo, vamos chamar a entrada Q.
                   ./ Partições inteiras de Q. Rende todas as combinações de
                          números inteiros que somam Q.
               @ RL2 Pegue a raiz quadrada de todos os números inteiros de cada partição.
             I # Mantenha apenas as partições invariantes em:
          sI # Descartando todos os não-inteiros. Isso basicamente mantém apenas o
                          partições que são formadas totalmente de quadrados perfeitos, mas
                          em vez de ter os próprios quadrados, temos suas raízes.
       eeD Obtenha a partição (digamos P) com o máximo mais alto.
 m Para cada d em P ...
  * d + 4d ... Rendimento d * (d + 4) = d ^ 2 + 4d, a fórmula usada em todas as respostas.
s Soma os resultados desse mapeamento e gera implicitamente.
Mr. Xcoder
fonte
1

Swift 4 , 111 99 84 78 bytes

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}

Experimente online!

Essa sensação ao implementar a raiz quadrada inteira manualmente é muito mais curta que a embutida ...

Ungolfed e Explained

// 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
}
Mr. Xcoder
fonte