こんにちは、ナナオです。

前回に引き続き競プロを実施していきたいと思います。

今回の問題は以下です。

デフォルト引数 | レベルアップ問題集 | プログラミング学習サイト【paizaラーニング】

実装

Goにはデフォルト引数を設定するような機能はありません。

ということで以下のブログを参考にしながら実装します。

【Golang】関数でデフォルト引数を実現させる方法 | Functional Options Pattern | しーまんブログ

具体的にはFunctional Options Patternというのを使うのが一般的なようです。

package main
import "fmt"
// OrderAlCohol関数に対するデフォルト値設定のためのOptions構造体を定義
type OrderAlCoholOptions struct {
    Amount int
}
type OrderAlCoholOption func(*OrderAlCoholOptions)
func Amount(amount int) OrderAlCoholOption {
    return func(opts *OrderAlCoholOptions) {
        opts.Amount = amount
    }
}
type Customer interface {
	OrderAlCohol(opts ...OrderAlCoholOption)
	OrderSoftdrink(amount int)
	OrderFood(amount int)
	GetTotalAmount() int
}
type Children struct {
    TotalAmount int
}
func (c *Children) OrderAlCohol(opts ...OrderAlCoholOption) {
    return
}
func (c *Children) OrderSoftdrink(amount int) {
    c.TotalAmount += amount
}
func (c *Children) OrderFood(amount int) {
    c.TotalAmount += amount
}
func (c *Children) GetTotalAmount() int {
    return c.TotalAmount
}
type Adult struct {
    Children
    HasOrderedAlcohol bool
}
func (a *Adult) OrderAlCohol(opts ...OrderAlCoholOption) {
    defaultOpts := &OrderAlCoholOptions {
        Amount: 500,
    }
    for _, opt := range opts {
        opt(defaultOpts)
    }
    a.TotalAmount += defaultOpts.Amount
    a.HasOrderedAlcohol = true
}
func (a *Adult) OrderSoftdrink(amount int) {
    a.TotalAmount += amount
}
func (a *Adult) OrderFood(amount int) {
    if a.HasOrderedAlcohol {
        a.TotalAmount += amount - 200
    } else {
        a.TotalAmount += amount
    }
}
func main(){
    var n, k int
    fmt.Scan(&n, &k)
    var c []Customer
    for i := 0; i < n; i++ {
        var age int
        fmt.Scan(&age)
        if age >= 20 {
            c = append(c, &Adult{
                Children: Children{TotalAmount: 0},
                HasOrderedAlcohol: false,
            })
        } else {
            c = append(c, &Children{TotalAmount: 0})
        }
    }
    for i := 0; i < k; i++ {
        var s, amount int
        var o string
        fmt.Scan(&s, &o)
        if o == "alcohol" {
            fmt.Scan(&amount)
            c[s - 1].OrderAlCohol(Amount(amount))
        } else if o == "softdrink" {
            fmt.Scan(&amount)
            c[s - 1].OrderSoftdrink(amount)
        } else if o == "food" {
            fmt.Scan(&amount)
            c[s - 1].OrderFood(amount)
        } else if o == "0" {
            c[s - 1].OrderAlCohol()
        }
    }
    for i := 0; i < n; i++ {
        fmt.Println(c[i].GetTotalAmount())
    }
}

まぁ競プロのコードにしては長いですが、業務コード感があって僕は割と好きです。

実装に時間はかかりましたが。。

ということで今回はこれで👍