【Golang】絶対値の出力方法を通して標準パッケージの関数やメソッドの大切さを再認識した話

2月 12, 2022

どもです。最近アウトドアに目覚め始めたsaisaiです。


今回はGolangにおけるパッケージの暗記と理解がどれほどコードを書く速度を加速させるのかを身を以て体験しましたので記事にしてみたいと思います。

絶対値の出力

いきなりですがみなさん、絶対値をご存知でしょうか。絶対値とは“その符号を無視して得られる非負の値を言う。"とWikipediaに記載されています。つまり、"5″の絶対値は"5″ですし、"-5″の絶対値も"5″です。0を原点とした距離と考えても分かりやすいかもしれません。


競技プログラミングの初級編などではこの絶対値を出力させる問題が度々見受けられます。例えば

標準入力される整数A、Bの差の絶対値を出力するコードを書いてください。

こんな問題が出題されたとしましょう。みなさんならどのようにコードを書くでしょうか。


プログラミングを学び始めて現在3ヶ月目の僕が何も調べずに無理やり作った悪い例が以下の通り。

package main

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

var sc = bufio.NewScanner(os.Stdin)

func nextLine() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func main() {
	s, t := nextLine(), nextLine()
	p := s - t
	if p < 0 {
		v := fmt.Sprint(p)
		fmt.Printf("%s\n", strings.TrimLeft(v, "-"))
	} else {
		fmt.Println(p)
	}
}

とりあえずなんとか知っている知識だけで実現させた感じです(笑)。酷く冗長なコードである上に絶対値をstring型で出力するコードとなっております。ますます残念…。

Abs関数を使ってみる

では次に、いろいろ調べてみた結果のコードが以下の通り。

package main

import (
	"fmt"
	"math"
)

func main() {
	s := []int{0, 0}
	fmt.Scanf("%d %d", &s[0], &s[1])
	a := int(s[0])
	b := int(s[1])
	c := a - b
	d := float64(c)
	fmt.Println(math.Abs(d))
}

随分とまぁすっきりしましたね…。ここまでコードをすっきりさせられたのは

math.Abs

この部分が非常に大きく関係しています。こちらはGoの標準パッケージである"math"パッケージの"Abs"関数を使用したコードです。Abs関数はfloat64型の引数を参照しその絶対値を返してくれるという正に今回のお題にぴったりの関数です。


もし事前に僕がこの関数を知っていれば、かなり早く目的のコードを書き終えることができていたことでしょう。


また、標準入力を受け取る方法も調べて改良してみました。こちらの方が必要標準パッケージも少なくすっきり書けますね!

ひとこと

同じ絶対値を出力するという処理を行う関数を書くにしても、パッケージや関数、あるいはメソッドなどに関して持っている知識によってどれだけ早くスタイリッシュなコードをかけるかが変わりそうです。


もちろんこのレベルであればググってしまえばいいだけの話なのですが、より高度な処理を求められた場合に"調べなくても対応できる"のか"調べる目処を瞬時に判断できる"のかといった面においても日頃どれだけ上記の項目についてキャッチアップしているのかがやはり大切になりそうです。


このブログでもいろんなパッケージや関数、メソッドについてアウトプットしていこうと思います。


ここまで読んでいただきありがとうございました!


-saisai-


↓本日のオススメ教材

Golang

Posted by CY