見出し画像

【Go言語】標準入力(2)

paizaラーニング レベルアップ問題集「標準入力メニュー」問題の続きです。


組になったデータの入力

入力が以下のような形式で与えられる問題例です。

整数の組

// N: 整数
// a_k, b_k: 整数

N
a_1 b_1
...
a_N b_N

文字列と整数の組

// N: 整数
// s_k: 文字列
// a_k: 整数

N
s_1 a_1
...
s_N a_N

整数の組の場合、N行2列の二次元配列・スライスで処理する手もありますが、データ型の異なる組の場合、後で型変換の処理が必要になり面倒です。
ここでは一次元配列・スライスをふた組使う手法を取ります。

以下のコードは文字列と整数の組のデータ(FINAL問題)の場合です。C言語ライクな書き方になります。

package main

import "fmt"

func main(){
    var n int
    fmt.Scan(&n)
    
    s := make([]string, n)
    a := make([]int, n)
    
    for i:=0; i<n; i++ {
        fmt.Scanf("%s %d", &s[i], &a[i])
    }
    
    for j:=0; j<n; j++ {
        fmt.Printf("%s %d\n", s[j], a[j])
    }
}

N行M列のデータの入力

N行M列の整数の入力

ステップごとにNとMの両方が定数、片方が定数、両方とも変数と変化していきますが、以下は両方とも変数である問題の解答例です。

入力部と出力部は様々な問題に流用できそうなので、関数にすると良いと考えます。

package main

import "fmt"

// 標準入力から整数値を受け取り、n行m列のスライスに入れる
func GenerateArray(n, m int) [][]int {
	result := make([][]int, n)
	for k := 0; k < n; k++ {
		result[k] = make([]int, m)
	}

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			fmt.Scan(&result[i][j])
		}
	}

	return result
}

// 二次元スライスを半角スペース区切りで標準出力に表示する
func ShowArray(arr [][]int) {
	n := len(arr)
	m := len(arr[0])

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			fmt.Print(arr[i][j])
			if j != m-1 {
				fmt.Print(" ")
			}
		}

		fmt.Println()
	}
}

func main() {
	var n, m int
	fmt.Scan(&n)
	fmt.Scan(&m)
	
	arr := GenerateArray(n, m)
	ShowArray(arr)
}

[FINAL問題]行ごとに要素数の異なる整数列の入力

要素数が不規則なデータの入力・出力のコードは若干面倒くさいです。

入力は、Pythonの場合、list(map(int, input().split())) の1文で1行のデータを受け取れます。Go言語でも strings.Split() メソッドがあるのですが、ライブラリのインポートが必要であり、Javaのようにスキャナーオブジェクトの宣言も必要です。
ここでは地道にfmt.Scan()を使ってスライスの要素に格納する手法を取ります。

出力部も、自作(AI作)のjoinメソッドを流用します。

package main

import (
    "fmt"
    "strings"
    "strconv"
)

// 半角スペース区切りの size 個の整数データ1行を標準入力で受け取り配列で返す
func ReadIntsWithSize(size int) []int {
    ints := make([]int, size)
    for i:=0; i<size; i++ {
        var num int
        fmt.Scan(&num)
        ints[i] = num
    }
    return ints
}

// 整数のスライスを、半角スペースで連結した文字列に変換する
func JoinIntsWithDelimiter(ints []int, delimiter string) string {
	strs := make([]string, len(ints))
	for i, num := range ints {
		strs[i] = strconv.Itoa(num)
	}
	return strings.Join(strs, delimiter)
}

func main(){
    var n int                    // データ行数
    fmt.Scan(&n)
    arr := make([][]int, 0)     // サイズ0の二次元スライスarrの準備

    // 1行のデータをスライスrowに格納し、arrにappendする 
    // これをn回繰り返す
    for i:=0; i<n; i++ {
        var size int       // 各行の1つ目の整数で列サイズが与えられる
        fmt.Scan(&size)
        
        var row []int
        row = ReadIntsWithSize(size)
        arr = append(arr, row)
    }
    
    for j:=0; j<n; j++ {
        fmt.Println(JoinIntsWithDelimiter(arr[j], " "))
    }
}

以上で標準入力メニューは終了です。

この記事が気に入ったらサポートをしてみませんか?