2
1

More than 3 years have passed since last update.

[Golang][競プロ]与えられた1~9の数値4つで任意に2桁の整数を2つ作り、それらの和が最大になる場合の、その和を求める問題について解説

Last updated at Posted at 2019-12-08

問題

1〜9までの数値が4つ与えられ、あなたはその4つの数値で、自由に2桁の整数を2つつくるとします。
様々な組み合わせがあるかと考えられますが、2つの2桁の整数を合計したときの、最も大きい値を調べて下さい。

たとえば、1 2 3 4という数値を与えられた場合、「12+34」や「13+24」などさまざまな組み合わせができます。
しかし、合計が最も大きくなるのは、この場合だと「42+31」であり、その合計は73です。
この場合の答えは73として下さい。

なお、この値は以下のような形で標準入力で渡されることとし、全て同じ値であることもありえるものとします。

与えられる数値の標準入力例1
1 2 3 4
与えられる数値の標準入力例1に対しての期待する回答
73

↑この場合、42+31= 「73」 が正解になります。

与えられる数値の標準入力例2
9 2 7 5
与えられる数値の標準入力例2に対しての期待する回答
167

↑この場合、92+75= 「167」 が正解になります。

与えられる数値の標準入力例2
9 9 9 9
与えられる数値の標準入力例2に対しての期待する回答
198

↑この場合、99+99= 「198」 が正解になります。

回答と解説

それでは解説していきます。

コード

回答したコード
package main
import "fmt"
func main(){

    s := []int{0,0,0,0}
    fmt.Scanf("%d %d %d %d", &s[0], &s[1], &s[2], &s[3])

    var 1st, 2nd, 3rd, 4th int
    for _, v := range s {
        if 1st <= v {
            4th = 3rd
            3rd = 2nd
            2nd = 1st
            1st = v
        } else if 2nd <= v {
            4th = 3rd
            3rd = 2nd
            2nd = v
        } else if 3rd <= v {
            4th = 3rd
            3rd = v
        } else {
            4th = v
        }

    }

    r := 1st * 10 + 3rd + 2nd * 10 + 4th
    fmt.Println(r)   
}

解説

基本的な考え方

今回は、与えられた数値の組み合わせについてはあまり考えませんでした

私が考えたポイントとしては…

  • 与えられた数値を、それぞれ大きい順に認識する
  • 「最も大きい数値」と「その次に大きい数値」を十の位にする必要があるので、10倍する
  • 残りの小さい2つの数値は一の位ということで、そのまま。(1倍する)
  • こうした上で、全部合計すれば求められている値が出る

という感じです。

解説用にコメント書きまくったコード
package main
import "fmt"
func main(){

    s := []int{0,0,0,0} // 標準入力をスライスに格納する形で受け取りたいと考えたので、0が4つ入ったスライス「s」を準備します。

    fmt.Scanf("%d %d %d %d", &s[0], &s[1], &s[2], &s[3]) // ここで標準入力を受け取っています。

    var 1st, 2nd, 3rd, 4th int // 最も大きいものからこの変数に入る想定で、1位〜4位までの「席」を準備します。

    for _, v := range s { // 受け取った標準入力をループで回します。

        if 1st <= v { // もし渡ってきた数値が、暫定1位にいる値より大きければ…

            4th = 3rd // 3位が4位に、2位が3位に、1位が2位にそれぞれ順位を落とします。
            3rd = 2nd
            2nd = 1st
            1st = v // そして1位の席に、渡ってきた数値が座ります。

        } else if 2nd <= v { // もし渡ってきた数値が、暫定1位よりは小さいけれど、暫定2位より大きければ…

            4th = 3rd // 3位と4位が順位を落とします。
            3rd = 2nd
            2nd = v // そして2位の席に、渡ってきた数値が座ります。

        } else if 3rd <= v {// もし渡ってきた数値が、暫定1位、2位よりは小さいけれど、暫定3位より大きければ…

            4th = 3rd //3位が4位に順位を落とします。
            3rd = v // そして3位の席には、渡ってきた数値が座ります。

        } else { // 最後に、暫定1、2、3位より小さい場合…

            4th = v // 渡ってきた数値は4位確定なので、4位の席に座ります。
        }

    }

    r := 1st * 10 + 3rd + 2nd * 10 + 4th // 1位と2位は十の位になる必要があるので10倍、3位と4位は一の位で良いので1倍して、全て合計します。

    fmt.Println(r) // 最後に結果を出力しておしまい!
}

さいごに

最後まで読んで頂き、ありがとうございます。
問題の解き方としての考え方は悪くない…と思うのですが、コードのロジックとしてはなんだか微妙な感じもします…
こうした方がもっと効率的だよ!とか、そういった意見があれば、ぜひお気軽にコメントして頂けると嬉しいです!

ありがとうございました!

2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1