ローマ軍の盾


26

サンドボックスの投稿(削除済み)

古いローマ軍隊は世界中で非常に有名です。これらの陣形では、ローマ軍団は幾何学形状(通常は長方形)にグループ化され、側面を保護し、シールドを使用してその側面を保護します。内部の位置にいる軍団はシールドを頭の上に置いて上部を覆い、側面の軍団は2つ以上のシールドを運んだ。彼は3つの盾を持っていました、誰かが5つの盾を持っていたフォーメーションに一人でいた場合はい、私は人間が5つの盾を運ぶことは不可能ですが、どういうわけか彼らはそれをしました)。このフォーメーションを使用して、すべてのローマ軍団は自分自身を保護し、当時最も困難な敵でした。

歴史は、ローマの将軍が、最高のフォーメーションの形状は正方形(行と列の同数の軍団員)であると述べていたと伝えています。問題は、次の目的で軍隊を分割する必要があるフォーメーション(およびサイズ)の数を把握することでした。

  • 軍団をフォーメーションから外さないでください(ただし、彼は単一の軍団フォーメーションを認めました)
  • 必要なシールドの量を減らす

一般的に、彼はいくつかの数学と計算を行った後、この2つの条件を達成する最良の方法は、可能な限り最大の正方形から始め、軍団がなくなるまで繰り返すことだと考えました


例:

彼の軍隊に35人の軍団がいる場合、フォーメーションは

  • 5x5の軍団の広場(これが可能な最大の広場です)。

残りの軍団(10)

  • 3x3の正方形

残りの軍団(1)

  • 1x1の正方形。

最後に次のようになります。

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

内部の位置にある軍団は頭の上に盾を置いて上部を覆った。必要なシールドは1つだけです。

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

側面の軍団は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 *               

誰かが角にいた場合、彼は3つのシールドを持っていました

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               

誰かがフォーメーションで一人だった場合、彼は5つのシールドを持っていました

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               

この編成には合計71のシールドが必要でした。


チャレンジ

  • X個の軍団に必要な盾の量を計算する

入力

  • 軍隊の軍団の数

出力

  • 必要なシールドの量。

テストケース

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


11
「5つの盾を運ぶ」ことのグーグルの結果はAmazon.com : Best-selling Nipple Shield Carrying Case, Perfect...そうですので、私は本当に知りません。彼らは実際に5つの盾を運んでいたのですか?それとも質問を機能させるためですか?
魔法のタコ

1
@MagicOctopusUrnイムはかなり確信して、あなたは答えが、私は誰かが5つの盾との戦いに外出する勇気を持っているとは思わないXD知っている
ルイス・フェリペ・デ・イエスムニョス

4
将軍の数学と計算は、可能な限り最大の二乗を繰り返すことでシールドを最小化すると結論付けるのは正しくありません。たとえば、32の軍団は、合計72シールドの5 * 5 + 2 * 2 + 1 * 1 + 1 * 1 + 1 * 1の正方形ではなく、合計64シールドの2つの4 * 4正方形に分割できます。
xnor

6
@xnor一般的な場合、一般は正しくありませんでしたが、一般は一般です(一般化すべきではありませんが)。
パジョン

2
@AJFaraday Asterixと merc 兵アナグマ
クリスH

回答:


14

パイソン260の 50 48バイト

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

オンラインでお試しください!

ゴルフをコーディングするのは初めてですが、最高のスイングを与えます!

方法:

合計入力にその合計最大の平方数のそれぞれです。n^2 + 4nn

編集1

@Jonathan Frechのおかげで50バイトに削減されました!

編集2

切り替えint(s**.5)s**.5//1@ovsのおかげでバイト2を保存します



2
2バイト節約するn*nよりも短いと思いn**2ます。それ以上に、私はpythonを書かないので言えません
ジュゼッペ


2
int(s**.5)に短縮できますs**.5//1
-ovs

2
@mypetlionそうです。//は、Python 2と3の両方のフロア分割です。両方のバージョンで3**.5//1評価さ1.0れます。
ovs

11

R51 50バイト

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

オンラインでお試しください!

yy2+4yxx

証明:

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


y24y

1
@ToddSewell確かに、それArnauldの説明であり、はるかにエレガントですが、これは私がアプローチした方法なので、私はそれに固執しています!幸いなことに、これは証明ゴルフの質問ではありません。
ジュゼッペ

10

JavaScript(ES7)、34バイト

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

オンラインでお試しください!

どうやって?

w=nsw

sw=w2+4w

w=3

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

w=1s1=5



4

ジュリア0.6、36バイト

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

オンラインでお試しください!

n2+4nn2n2n22n24n22シールド。最後に、4つのコーナーに4つの3があるため、12のシールドが追加されます。

n22+4n22+43=n2+44n+8n16+12=n2+4n

ゴルフをしていない:

!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

(これはで35バイトで行うこともできますがn>0?(s=isqrt(n))*s+4s+f(n-s*s):0、新しい非推奨の警告(スペースは?and が必要です:)を避けるためにJulia 0.7向けに書いています。)


シールド数についてのもう1つの複雑な説明は、@ Giuseppeの答えに関する私のコメントを参照してください。
トッドシーウェル

2
@ToddSewellええ、面積+境界線はよりエレガントな方法です。私はそうはしませんでしたが、ジュゼッペと同様に、私の意図は式の最も近い証拠を与えることよりも私のアプローチを説明することです。
スンダ


3

Brachylog、26バイト

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

オンラインでお試しください!

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

2

Retina 0.8.2、28バイト

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

オンラインでお試しください!リンクにはテストケースが含まれます。説明:

.+
$*

10進数に変換します。

(\G1|11\1)+

奇数に一致します。基を介して最初のパスは、\1まだ存在しないので、唯一の\G1一致することができ、1以降の一致が一致することはできません一致する\G1ので、\Gこれに代えて、我々は一致しなければならない、試合の開始時にのみマッチ11\12以上であると前の試合。できる限り多くの奇数を一致させます。したがって、最後のキャプチャはその辺の2倍未満であるのに対し、合計一致は2進数になります。

$&11$1$1

$&n2$12n1n2+4n=n2+2+22n1

.

合計して10進数に変換します。


2

05AB1E、17 バイト

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

オンラインそれを試してみたり、すべてのテストケースを確認してください

回避策ΔDtïÐns4*+Šn-}O15バイト)は機能していないようです。デバッグモードでオンラインで試して、意味を確認してください。私はそれから行くことを期待する[45,'35',25][45,10]した後-の、次の反復Δが、どうやらそれは、最後の値を除き、スタックをクリアし、となり[10]、これは動作やバグを意図していないことを確認場合...一番最後に0になります.. (編集:意図されています。下を参照してください。)

説明:

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

編集:どうやら上記で説明した動作Δが意図されています。ここで@ Mr.Xcoderによって提供される2つの17バイトの選択肢Δは、global_arrayに値を(withで^)入れ、後でそれらを再度取得する(withで)ことによって使用します¯

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

オンラインそれを試してみたり、すべてのテストケースを確認してください

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

オンラインそれを試してみたり、すべてのテストケースを確認してください






1

PHP、67バイト

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

実行するには:

php -n <filename> <n>

例:

php -n roman_army_shields.php 35

または、オンラインでお試しください!


-Rオプションを使用すると、このバージョンは60バイトになります

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

例:

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

(Linux上で、交換する"'


注:これはArnauldの答えの素晴らしい式を使用しているため、それより短いものは見つかりませんでした。


1

Pyth、19バイト

を使用して呼び出す必要がある再帰関数y(リンクを参照)。

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

ここで試してみてください!

Pyth、21バイト

改訂履歴は非常に面白いですが、より高速なバージョンが必要な場合は必ずアクセスしてください:)

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

ここで試してみてください!

説明

sm*d+4deeDsI#I#@RL2./完全なプログラム、入力Qを呼び出しましょう。
                   ./ Qの整数分割。正のすべての組み合わせを生成します。
                          合計Qの整数
               @ RL2各パーティションのすべての整数の平方根を取ります。
             I#以下で不変なパーティションのみを保持します。
          sI#すべての非整数を破棄します。これは基本的に
                          完全に正方形で完全に形成されたパーティション
                          正方形自体ではなく、そのルーツがあります。
       eeD最大値が最大のパーティション(Pなど)を取得します。
 m Pの各dについて...
  * d + 4d ...収量d *(d + 4)= d ^ 2 + 4d、すべての回答で使用される式。
■このマッピングの結果を合計し、暗黙的に出力します。

1

スイフト4111の99 84 78バイト

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}

オンラインでお試しください!

整数の平方根を手動で実装するときの感覚は、組み込みのものよりもはるかに短い...

非ゴルフと説明

// 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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.