2
2

More than 3 years have passed since last update.

Go で競技プログラミング攻略1 (AtCoder Beginners Selection 1~6)

Last updated at Posted at 2020-01-29

はじめに

この記事は自分のためにメモとして書いてあるので書き方はテキトー
間違っていたりこうしたらいいよっていうのは教えていただけるとありがたいです
競プロはマジの初心者スタートでやっていきたいと思います

Tutrial

A - Welcome to AtCoder

答え見えちゃったので忘れたフリして書いていく。。。うまくいかねぇ
仕方なく答えチラ見

ポインタ使ってやってるヤンケーーー!!

ポインタはC言語学ぶ上でつまづいてなんだか分からず使ってたあのやつ!!!(結局わからん)

調べてみると Scanfに指定する変数はポインタで渡さないと行けないらしい。
Scanf("%d", &a)
fmtはCから派生したものらしい

しかたねえ、、、
良さそうな記事見つけたのでそれ読んで理解できなかったら、なんとなくで、、、、
Goで学ぶポインタとアドレス

んー、、、まあ、なんとなく
どんな時に使うといいのか正直わからん。
まあいいや。 次いこう



ABC086A - Product

main.go
package main

import "fmt"

func main() {
    var a, b int
    fmt.Scanf("%d %d", &a, &b)
    if (a*b)%2 == 0 {
        fmt.Printf("Even")
    } else {
        fmt.Printf("Odd")
    }
}

hahaha!!! 行けるやんおれ





ABC081A - Placing Marbles

1数字ずつ読み込むのって
fmt.Scanf("%d%d%d", &s1, &s2, &s3)
でええんか??
うまくいかんよなw だと思った


標準入力で一文字ずつを入力する方法をggる

数学的に処理する方法を発見
Go で int を1桁ずつ slice に入れる

これ通りに書いていこう

拡張forの書き方


    for index, value := range numList {
        処理内容
    }


intを一桁ずつ配列にいれる

main.go
func splitNumber(num int, numList []int) []int {
    for 0 > num {
        return splitNumber(num/10, append(numList, num%10))
    }
    return numList
}

むむっ!!!!

ここで問題発生
配列にappendしても数値が思い通りに入ってくれていない

これはまたしてもポインタのせいか???
これは、、、
参照渡しになっているからだあぁぁぁ!!!
心優しい方がgoには、参照渡しなんて存在しねえ。戻り値を変数に代入し忘れてるだけや

ということであっさり解決

main.go
package main

import "fmt"

func main() {
    var S int
    var numList []int
    var sum int
    fmt.Scanf("%d", &S)

    numList = splitNumber(S, numList)
//合計値を算出
    for _, v := range numList {
        sum += v
    }
    fmt.Printf("%d", sum)
}

//numを一桁ずつnumListに格納
func splitNumber(num int, numList []int) []int {
    for num > 0 {
        return splitNumber(num/10, append(numList, num%10))
    }
    return numList
}

おっけい!クリア!!

ABC081B - Shift only

これは入力をスプリットして配列に格納してなんとかすんじゃね?
って思ったので書いてみることに

文字列1行を読み込む

func scanStringLine() string {
    var strLine string
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan()
    strLine = scanner.Text()
    return strLine
}

入力をスプリットしていろいろするならstring型の配列からint型の配列の方がいいよね
ってことで変換する関数を書いてみる

[]string から []intに変換

func StrToInt(strList []string) []int {
    var numList []int
    var toInt int
    for _, v := range strList {
        toInt, _ = strconv.Atoi(v)
        numList = append(numList, toInt)
    }
    return numList
}

ok ok~~
問題文は 与えられた数字が全て2で割れるなら、与えられた数字を2で割る。それができる回数を求めよ
なので
カウンターを書いていく

func counter(count int, numList []int) int {
    flag := false
    for flag == false {
        for i, v := range numList {
            if v%2 == 0 {
                numList[i] = v / 2
            } else {
                flag = true
                return count
            }
        }
        count++
    }
    return count
}



......絶対もっと上手い書き方がある気がする
とりあえずガッチャンコしてみよう

main.go
package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    var N int
    var strNumbers string
    var numList []int
    var arr []string

    //最初の一文字
    fmt.Scanf("%d", &N)
    strNumbers = scanStringLine()

    arr = strings.Split(strNumbers, " ")
    numList = StrToInt(arr)
    fmt.Println(counter(0, numList))
}

func counter(count int, numList []int) int {
    flag := false
    for flag == false {
        for i, v := range numList {
            if v%2 == 0 {
                numList[i] = v / 2
            } else {
                flag = true
                return count
            }
        }
        count++
    }
    return count
}

//文字列を1列入力
func scanStringLine() string {
    var strLine string
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan()
    strLine = scanner.Text()
    return strLine
}

//string型の配列からint型の配列に変換
func StrToInt(strList []string) []int {
    var numList []int
    var toInt int
    for _, v := range strList {
        toInt, _ = strconv.Atoi(v)
        numList = append(numList, toInt)
    }
    return numList
}

これでテイシュッツ!

クリア!!

ABC087B - Coins

うーん、、、
上手いやり方が思いつかない、、、

詰まってしまったのでggる。
ほう、普通に総当たり的に全てを試して行っている、、、

思いついたけどこれが正解みたい。
原始的な方法もやってみることが大事そう

ということで書いていく

package main

import "fmt"

func main() {
    //500円玉の枚数
    var a int
    //100円玉の枚数
    var b int
    //50円玉の枚数
    var c int
    //合計金額
    var x int

    fmt.Scanf("%d\n", &a)
    fmt.Scanf("%d\n", &b)
    fmt.Scanf("%d\n", &c)
    fmt.Scanf("%d\n", &x)
    fmt.Println(counterCoins(a, b, c, x))
}

func counterCoins(a int, b int, c int, x int) int {
    count := 0

    for i := 0; i <= a; i++ {
        for j := 0; j <= b; j++ {
            for k := 0; k <= c; k++ {
                if i*500+j*100+k*50 == x {
                    count++
                }
            }
        }
    }
    return count
}

ABC083B - Some Sums

みた感じ ABC081A - Placing Marbles で使った1桁を配列にいれるのを使いそう
チャチャット書いてみる

1桁ずつ配列にいれ桁ごとの総和を戻り値にして返す

//1桁ずつ配列にいれ桁ごとの総和を戻り値にして返す
func splitNumberSum(num int, numList []int) int {
    sum := 0
    for num > 0 {
        return splitNumberSum(num/10, append(numList, num%10))
    }
    for _, v := range numList {
        sum += v
    }
    return sum
}

これだとあんまりカッコよくない(numListらへんが)ので改造

桁の総和を戻り値にして返す

//桁の総和を戻り値にして返す
func splitNumberSum(num int, tmp int) int {
    for num > 0 {
        tmp += num % 10
        return splitNumberSum(num/10, tmp)
    }
    return tmp
}

ええやん
カッコよくなった!!

あとは
A,Bの条件に合うものは加算する
をNまでfor文で回す

//A,Bの条件に合うかどうか判定し、真であればAnswerSumに加算する
func countSum(N int, A int, B int) int {
    AnswerSum := 0
    sum := 0
    for i := 1; i <= N; i++ {
        sum = splitNumberSum(i, 0)
        if A <= sum && sum <= B {
            AnswerSum += i
        }
    }
    return AnswerSum
}

あとはこの二つとmain関数をガッチャンコ

package main

import "fmt"

func main() {
    var N int
    var A int
    var B int

    fmt.Scanf("%d %d %d", &N, &A, &B)
    fmt.Println(countSum(N, A, B))
}

func countSum(N int, A int, B int) int {
    AnswerSum := 0
    sum := 0
    for i := 1; i <= N; i++ {
        sum = splitNumberSum(i, 0)
        if A <= sum && sum <= B {
            AnswerSum += i
        }
    }
    return AnswerSum
}

//桁の総和を戻り値にして返す
func splitNumberSum(num int, tmp int) int {
    for num > 0 {
        tmp += num % 10
        return splitNumberSum(num/10, tmp)
    }
    return tmp
}

できた!!!!

思ったこと

最初だからか標準入力系が多い気がした。自分だけの便利パッケージ作っておくと後々楽そう。
意外とつまずきまくってたので、なんとなく勉強しただけなんだなぁと実感。
でも、こういうのが成長には大切だと思うので頑張るんば。

2
2
3

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
2